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 static uno::Reference
< uno::XInterface
> xInst
= (cppu::OWeakObject
*) new ScaPricingAddIn();
181 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
pricing_component_getFactory(
182 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
186 if ( pServiceManager
&&
187 OUString::createFromAscii( pImplName
) == ScaPricingAddIn::getImplementationName_Static() )
189 uno::Reference
< lang::XSingleServiceFactory
> xFactory( cppu::createOneInstanceFactory(
190 reinterpret_cast< lang::XMultiServiceFactory
* >( pServiceManager
),
191 ScaPricingAddIn::getImplementationName_Static(),
192 ScaPricingAddIn_CreateInstance
,
193 ScaPricingAddIn::getSupportedServiceNames_Static() ) );
198 pRet
= xFactory
.get();
207 // "normal" service implementation
208 ScaPricingAddIn::ScaPricingAddIn() :
211 pFuncDataList( NULL
)
215 ScaPricingAddIn::~ScaPricingAddIn()
218 delete pFuncDataList
;
220 delete[] pDefLocales
;
222 // pResMgr already deleted (_all_ resource managers are deleted _before_ this dtor is called)
225 static const sal_Char
* pLang
[] = { "de", "en" };
226 static const sal_Char
* pCoun
[] = { "DE", "US" };
227 static const sal_uInt32 nNumOfLoc
= SAL_N_ELEMENTS( pLang
);
229 void ScaPricingAddIn::InitDefLocales()
231 pDefLocales
= new lang::Locale
[ nNumOfLoc
];
233 for( sal_uInt32 nIndex
= 0; nIndex
< nNumOfLoc
; nIndex
++ )
235 pDefLocales
[ nIndex
].Language
= OUString::createFromAscii( pLang
[ nIndex
] );
236 pDefLocales
[ nIndex
].Country
= OUString::createFromAscii( pCoun
[ nIndex
] );
240 const lang::Locale
& ScaPricingAddIn::GetLocale( sal_uInt32 nIndex
)
245 return (nIndex
< sizeof( pLang
)) ? pDefLocales
[ nIndex
] : aFuncLoc
;
248 ResMgr
& ScaPricingAddIn::GetResMgr() throw( uno::RuntimeException
)
252 InitData(); // try to get resource manager
254 throw uno::RuntimeException();
259 void ScaPricingAddIn::InitData()
265 OString
aModName( "pricing" );
266 pResMgr
= ResMgr::CreateResMgr( aModName
.getStr(), LanguageTag( aFuncLoc
) );
269 delete pFuncDataList
;
271 pFuncDataList
= pResMgr
? new ScaFuncDataList( *pResMgr
) : NULL
;
280 OUString
ScaPricingAddIn::GetDisplFuncStr( sal_uInt16 nResId
) throw( uno::RuntimeException
)
282 return ScaResStringLoader( RID_PRICING_FUNCTION_NAMES
, nResId
, GetResMgr() ).GetString();
285 OUString
ScaPricingAddIn::GetFuncDescrStr( sal_uInt16 nResId
, sal_uInt16 nStrIndex
) throw( uno::RuntimeException
)
289 ScaResPublisher
aResPubl( ScaResId( RID_PRICING_FUNCTION_DESCRIPTIONS
, GetResMgr() ) );
290 ScaResId
aResId( nResId
, GetResMgr() );
291 aResId
.SetRT( RSC_RESOURCE
);
293 if( aResPubl
.IsAvailableRes( aResId
) )
294 ScaFuncRes
aSubRes( aResId
, GetResMgr(), nStrIndex
, aRet
);
296 aResPubl
.FreeResource();
300 OUString
ScaPricingAddIn::getImplementationName_Static()
302 return OUString( MY_IMPLNAME
);
305 uno::Sequence
< OUString
> ScaPricingAddIn::getSupportedServiceNames_Static()
307 uno::Sequence
< OUString
> aRet( 2 );
308 OUString
* pArray
= aRet
.getArray();
309 pArray
[0] = OUString( ADDIN_SERVICE
);
310 pArray
[1] = OUString( MY_SERVICE
);
315 OUString SAL_CALL
ScaPricingAddIn::getServiceName() throw( uno::RuntimeException
, std::exception
)
317 // name of specific AddIn service
318 return OUString( MY_SERVICE
);
322 OUString SAL_CALL
ScaPricingAddIn::getImplementationName() throw( uno::RuntimeException
, std::exception
)
324 return getImplementationName_Static();
327 sal_Bool SAL_CALL
ScaPricingAddIn::supportsService( const OUString
& aServiceName
) throw( uno::RuntimeException
, std::exception
)
329 return cppu::supportsService(this, aServiceName
);
332 uno::Sequence
< OUString
> SAL_CALL
ScaPricingAddIn::getSupportedServiceNames() throw( uno::RuntimeException
, std::exception
)
334 return getSupportedServiceNames_Static();
338 void SAL_CALL
ScaPricingAddIn::setLocale( const lang::Locale
& eLocale
) throw( uno::RuntimeException
, std::exception
)
341 InitData(); // change of locale invalidates resources!
344 lang::Locale SAL_CALL
ScaPricingAddIn::getLocale() throw( uno::RuntimeException
, std::exception
)
349 // function descriptions start here
351 OUString SAL_CALL
ScaPricingAddIn::getProgrammaticFuntionName( const OUString
& ) throw( uno::RuntimeException
, std::exception
)
354 // (but should be implemented for other uses of the AddIn service)
358 OUString SAL_CALL
ScaPricingAddIn::getDisplayFunctionName( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
362 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
365 aRet
= GetDisplFuncStr( pFData
->GetUINameID() );
366 if( pFData
->IsDouble() )
367 aRet
+= STR_FROM_ANSI( "_ADD" );
371 aRet
= STR_FROM_ANSI( "UNKNOWNFUNC_" );
372 aRet
+= aProgrammaticName
;
378 OUString SAL_CALL
ScaPricingAddIn::getFunctionDescription( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
382 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
384 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), 1 );
389 OUString SAL_CALL
ScaPricingAddIn::getDisplayArgumentName(
390 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
, std::exception
)
394 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
395 if( pFData
&& (nArgument
<= 0xFFFF) )
397 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
399 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
);
401 aRet
= STR_FROM_ANSI( "internal" );
407 OUString SAL_CALL
ScaPricingAddIn::getArgumentDescription(
408 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
, std::exception
)
412 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
413 if( pFData
&& (nArgument
<= 0xFFFF) )
415 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
417 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
+ 1 );
419 aRet
= STR_FROM_ANSI( "for internal use only" );
425 OUString SAL_CALL
ScaPricingAddIn::getProgrammaticCategoryName(
426 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
430 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
433 switch( pFData
->GetCategory() )
435 case ScaCat_DateTime
: aRet
= STR_FROM_ANSI( "Date&Time" ); break;
436 case ScaCat_Text
: aRet
= STR_FROM_ANSI( "Text" ); break;
437 case ScaCat_Finance
: aRet
= STR_FROM_ANSI( "Financial" ); break;
438 case ScaCat_Inf
: aRet
= STR_FROM_ANSI( "Information" ); break;
439 case ScaCat_Math
: aRet
= STR_FROM_ANSI( "Mathematical" ); break;
440 case ScaCat_Tech
: aRet
= STR_FROM_ANSI( "Technical" ); break;
441 default: // to prevent compiler warnings
447 aRet
= STR_FROM_ANSI( "Add-In" );
451 OUString SAL_CALL
ScaPricingAddIn::getDisplayCategoryName(
452 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
454 return getProgrammaticCategoryName( aProgrammaticName
);
457 // XCompatibilityNames
458 uno::Sequence
< sheet::LocalizedName
> SAL_CALL
ScaPricingAddIn::getCompatibilityNames(
459 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
461 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
463 return uno::Sequence
< sheet::LocalizedName
>( 0 );
465 const ScaStringList
& rStrList
= pFData
->GetCompNameList();
466 sal_uInt32 nCount
= rStrList
.Count();
468 uno::Sequence
< sheet::LocalizedName
> aRet( nCount
);
469 sheet::LocalizedName
* pArray
= aRet
.getArray();
471 for( sal_uInt32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
472 pArray
[ nIndex
] = sheet::LocalizedName( GetLocale( nIndex
), *rStrList
.Get( nIndex
) );
477 // actual function implementation starts here
478 // auxillary input handling functions
481 bool getinput_putcall(bs::types::PutCall
& pc
, const OUString
& str
) {
482 if(str
.startsWith("c")) {
484 } else if(str
.startsWith("p")) {
492 bool getinput_putcall(bs::types::PutCall
& pc
, const uno::Any
& anyval
) {
494 if(anyval
.getValueTypeClass() == uno::TypeClass_STRING
) {
496 } else if(anyval
.getValueTypeClass() == uno::TypeClass_VOID
) {
497 str
="c"; // call as default
501 return getinput_putcall(pc
, str
);
504 bool getinput_strike(double& strike
, const uno::Any
& anyval
) {
505 if(anyval
.getValueTypeClass() == uno::TypeClass_DOUBLE
) {
507 } else if(anyval
.getValueTypeClass() == uno::TypeClass_VOID
) {
508 strike
=-1.0; // -1 as default (means not set)
515 bool getinput_inout(bs::types::BarrierKIO
& kio
, const OUString
& str
) {
516 if(str
.startsWith("i")) {
517 kio
=bs::types::KnockIn
;
518 } else if(str
.startsWith("o")) {
519 kio
=bs::types::KnockOut
;
526 bool getinput_barrier(bs::types::BarrierActive
& cont
, const OUString
& str
) {
527 if(str
.startsWith("c")) {
528 cont
=bs::types::Continuous
;
529 } else if(str
.startsWith("e")) {
530 cont
=bs::types::Maturity
;
537 bool getinput_fordom(bs::types::ForDom
& fd
, const OUString
& str
) {
538 if(str
.startsWith("f")) {
539 fd
=bs::types::Foreign
;
540 } else if(str
.startsWith("d")) {
541 fd
=bs::types::Domestic
;
548 bool getinput_greek(bs::types::Greeks
& greek
, const uno::Any
& anyval
) {
550 if(anyval
.getValueTypeClass() == uno::TypeClass_STRING
) {
552 } else if(anyval
.getValueTypeClass() == uno::TypeClass_VOID
) {
558 if(str
.equalsAscii("value") || str
.equalsAscii("price") ||
559 str
.equalsAscii("v") || str
.equalsAscii("p") ) {
560 greek
=bs::types::Value
;
561 } else if(str
.equalsAscii("delta") || str
.equalsAscii("d")) {
562 greek
=bs::types::Delta
;
563 } else if(str
.equalsAscii("gamma") || str
.equalsAscii("g")) {
564 greek
=bs::types::Gamma
;
565 } else if(str
.equalsAscii("theta") || str
.equalsAscii("t")) {
566 greek
=bs::types::Theta
;
567 } else if(str
.equalsAscii("vega") || str
.equalsAscii("e")) {
568 greek
=bs::types::Vega
;
569 } else if(str
.equalsAscii("volga") || str
.equalsAscii("o")) {
570 greek
=bs::types::Volga
;
571 } else if(str
.equalsAscii("vanna") || str
.equalsAscii("a")) {
572 greek
=bs::types::Vanna
;
573 } else if(str
.equalsAscii("rho") || str
.equalsAscii("r")) {
574 greek
=bs::types::Rho_d
;
575 } else if(str
.equalsAscii("rhof") || str
.equalsAscii("f")) {
576 greek
=bs::types::Rho_f
;
583 } // namespace for auxillary functions
586 double SAL_CALL
ScaPricingAddIn::getOptBarrier( double spot
, double vol
,
587 double r
, double rf
, double T
, double strike
,
588 double barrier_low
, double barrier_up
, double rebate
,
589 const OUString
& put_call
, const OUString
& in_out
,
590 const OUString
& barriercont
, const uno::Any
& greekstr
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
592 bs::types::PutCall pc
;
593 bs::types::BarrierKIO kio
;
594 bs::types::BarrierActive bcont
;
595 bs::types::Greeks greek
;
596 // read and check input values
597 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 || strike
<0.0 ||
598 !getinput_putcall(pc
,put_call
) ||
599 !getinput_inout(kio
,in_out
) ||
600 !getinput_barrier(bcont
,barriercont
) ||
601 !getinput_greek(greek
,greekstr
) ){
602 throw lang::IllegalArgumentException();
605 double fRet
=bs::barrier(spot
,vol
,r
,rf
,T
,strike
, barrier_low
,barrier_up
,
606 rebate
,pc
,kio
,bcont
,greek
);
608 RETURN_FINITE( fRet
);
612 double SAL_CALL
ScaPricingAddIn::getOptTouch( double spot
, double vol
,
613 double r
, double rf
, double T
,
614 double barrier_low
, double barrier_up
,
615 const OUString
& for_dom
, const OUString
& in_out
,
616 const OUString
& barriercont
, const uno::Any
& greekstr
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
618 bs::types::ForDom fd
;
619 bs::types::BarrierKIO kio
;
620 bs::types::BarrierActive bcont
;
621 bs::types::Greeks greek
;
622 // read and check input values
623 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 ||
624 !getinput_fordom(fd
,for_dom
) ||
625 !getinput_inout(kio
,in_out
) ||
626 !getinput_barrier(bcont
,barriercont
) ||
627 !getinput_greek(greek
,greekstr
) ){
628 throw lang::IllegalArgumentException();
631 double fRet
=bs::touch(spot
,vol
,r
,rf
,T
,barrier_low
,barrier_up
,
634 RETURN_FINITE( fRet
);
638 double SAL_CALL
ScaPricingAddIn::getOptProbHit( double spot
, double vol
,
640 double barrier_low
, double barrier_up
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
642 // read and check input values
643 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 ) {
644 throw lang::IllegalArgumentException();
647 double fRet
=bs::prob_hit(spot
,vol
,mu
,T
,barrier_low
,barrier_up
);
649 RETURN_FINITE( fRet
);
652 // OPT_PROB_INMONEY(...)
653 double SAL_CALL
ScaPricingAddIn::getOptProbInMoney( double spot
, double vol
,
655 double barrier_low
, double barrier_up
,
656 const uno::Any
& strikeval
, const uno::Any
& put_call
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
658 bs::types::PutCall pc
=bs::types::Call
;
661 // read and check input values
662 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 ||
663 !getinput_putcall(pc
,put_call
) ||
664 !getinput_strike(K
,strikeval
) ) {
665 throw lang::IllegalArgumentException();
668 double fRet
=bs::prob_in_money(spot
,vol
,mu
,T
,K
,barrier_low
,barrier_up
,pc
);
670 RETURN_FINITE( fRet
);
674 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */