Bump version to 5.0-14
[LibreOffice.git] / scaddins / source / pricing / pricing.cxx
blobee23ef4dd36a94c1fe81deb3674a8e49f546a84e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
31 #include <iostream>
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;
51 ScaList::ScaList() :
52 pData( new void*[ nStartSize ] ),
53 nSize( nStartSize ),
54 nCount( 0 ),
55 nCurr( 0 )
59 ScaList::~ScaList()
61 delete[] pData;
64 void ScaList::_Grow()
66 nSize += nIncrSize;
68 void** pNewData = new void*[ nSize ];
69 memcpy( pNewData, pData, nCount * sizeof( void* ) );
71 delete[] pData;
72 pData = pNewData;
75 ScaStringList::~ScaStringList()
77 for( OUString* pStr = First(); pStr; pStr = Next() )
78 delete pStr;
81 ScaResId::ScaResId( sal_uInt16 nId, ResMgr& rResMgr ) :
82 ResId( nId, 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)
101 #undef FUNCDATA
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
126 if( !bWithOpt )
127 nParam++;
128 return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
131 ScaFuncDataList::ScaFuncDataList( ResMgr& rResMgr ) :
132 nLast( 0xFFFFFFFF )
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() )
141 delete pFData;
144 const ScaFuncData* ScaFuncDataList::Get( const OUString& rProgrammaticName ) const
146 if( aLastName == rProgrammaticName ){
147 return Get( nLast );
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;
157 return pCurr;
160 return NULL;
163 ScaFuncRes::ScaFuncRes( ResId& rResId, ResMgr& rResMgr, sal_uInt16 nIndex, OUString& rRet ) :
164 Resource( rResId )
166 rRet = ScaResId(nIndex, rResMgr).toString();
167 FreeResource();
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();
177 extern "C" {
179 SAL_DLLPUBLIC_EXPORT void * SAL_CALL pricing_component_getFactory(
180 const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
182 void* pRet = 0;
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() ) );
193 if (xFactory.is())
195 xFactory->acquire();
196 pRet = xFactory.get();
200 return pRet;
203 } // extern C
205 // "normal" service implementation
206 ScaPricingAddIn::ScaPricingAddIn() :
207 pDefLocales( NULL ),
208 pResMgr( NULL ),
209 pFuncDataList( NULL )
213 ScaPricingAddIn::~ScaPricingAddIn()
215 delete pFuncDataList;
216 delete pResMgr;
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 )
237 if( !pDefLocales )
238 InitDefLocales();
240 return (nIndex < sizeof( pLang )) ? pDefLocales[ nIndex ] : aFuncLoc;
243 ResMgr& ScaPricingAddIn::GetResMgr() throw( uno::RuntimeException )
245 if( !pResMgr )
247 InitData(); // try to get resource manager
248 if( !pResMgr )
249 throw uno::RuntimeException();
251 return *pResMgr;
254 void ScaPricingAddIn::InitData()
256 delete pResMgr;
257 pResMgr = ResMgr::CreateResMgr("pricing", LanguageTag( aFuncLoc) );
258 delete pFuncDataList;
260 pFuncDataList = pResMgr ? new ScaFuncDataList( *pResMgr ) : NULL;
262 if( pDefLocales )
264 delete pDefLocales;
265 pDefLocales = 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 )
276 OUString aRet;
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();
286 return aRet;
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;
300 return aRet;
303 // XServiceName
304 OUString SAL_CALL ScaPricingAddIn::getServiceName() throw( uno::RuntimeException, std::exception )
306 // name of specific AddIn service
307 return OUString( MY_SERVICE );
310 // XServiceInfo
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();
326 // XLocalizable
327 void SAL_CALL ScaPricingAddIn::setLocale( const lang::Locale& eLocale ) throw( uno::RuntimeException, std::exception )
329 aFuncLoc = eLocale;
330 InitData(); // change of locale invalidates resources!
333 lang::Locale SAL_CALL ScaPricingAddIn::getLocale() throw( uno::RuntimeException, std::exception )
335 return aFuncLoc;
338 // function descriptions start here
339 // XAddIn
340 OUString SAL_CALL ScaPricingAddIn::getProgrammaticFuntionName( const OUString& ) throw( uno::RuntimeException, std::exception )
342 // not used by calc
343 // (but should be implemented for other uses of the AddIn service)
344 return OUString();
347 OUString SAL_CALL ScaPricingAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
349 OUString aRet;
351 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
352 if( pFData )
354 aRet = GetDisplFuncStr( pFData->GetUINameID() );
355 if( pFData->IsDouble() )
356 aRet += STR_FROM_ANSI( "_ADD" );
358 else
360 aRet = STR_FROM_ANSI( "UNKNOWNFUNC_" );
361 aRet += aProgrammaticName;
364 return aRet;
367 OUString SAL_CALL ScaPricingAddIn::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
369 OUString aRet;
371 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
372 if( pFData )
373 aRet = GetFuncDescrStr( pFData->GetDescrID(), 1 );
375 return aRet;
378 OUString SAL_CALL ScaPricingAddIn::getDisplayArgumentName(
379 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
381 OUString aRet;
383 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
384 if( pFData && (nArgument <= 0xFFFF) )
386 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
387 if( nStr )
388 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr );
389 else
390 aRet = STR_FROM_ANSI( "internal" );
393 return aRet;
396 OUString SAL_CALL ScaPricingAddIn::getArgumentDescription(
397 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
399 OUString aRet;
401 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
402 if( pFData && (nArgument <= 0xFFFF) )
404 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
405 if( nStr )
406 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr + 1 );
407 else
408 aRet = STR_FROM_ANSI( "for internal use only" );
411 return aRet;
414 OUString SAL_CALL ScaPricingAddIn::getProgrammaticCategoryName(
415 const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
417 OUString aRet;
419 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
420 if( pFData )
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
431 default:
432 break;
436 if( aRet.isEmpty() )
437 aRet = STR_FROM_ANSI( "Add-In" );
438 return aRet;
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 );
452 if( !pFData )
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 ) );
464 return aRet;
467 // actual function implementation starts here
468 // auxiliary input handling functions
469 namespace {
471 bool getinput_putcall(bs::types::PutCall& pc, const OUString& str) {
472 if(str.startsWith("c")) {
473 pc=bs::types::Call;
474 } else if(str.startsWith("p")) {
475 pc=bs::types::Put;
476 } else {
477 return false;
479 return true;
482 bool getinput_putcall(bs::types::PutCall& pc, const uno::Any& anyval) {
483 OUString str;
484 if(anyval.getValueTypeClass() == uno::TypeClass_STRING) {
485 anyval >>= str;
486 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
487 str="c"; // call as default
488 } else {
489 return false;
491 return getinput_putcall(pc, str);
494 bool getinput_strike(double& strike, const uno::Any& anyval) {
495 if(anyval.getValueTypeClass() == uno::TypeClass_DOUBLE) {
496 anyval >>= strike;
497 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
498 strike=-1.0; // -1 as default (means not set)
499 } else {
500 return false;
502 return true;
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;
510 } else {
511 return false;
513 return true;
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;
521 } else {
522 return false;
524 return true;
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;
532 } else {
533 return false;
535 return true;
538 bool getinput_greek(bs::types::Greeks& greek, const uno::Any& anyval) {
539 OUString str;
540 if(anyval.getValueTypeClass() == uno::TypeClass_STRING) {
541 anyval >>= str;
542 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
543 str="value";
544 } else {
545 return false;
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;
566 } else {
567 return false;
569 return true;
572 } // namespace for auxiliary functions
574 // OPT_BARRIER(...)
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 );
600 // OPT_TOUCH(...)
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,
621 fd,kio,bcont,greek);
623 RETURN_FINITE( fRet );
626 // OPT_PRB_HIT(...)
627 double SAL_CALL ScaPricingAddIn::getOptProbHit( double spot, double vol,
628 double mu, double T,
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,
643 double mu, double T,
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;
648 double K;
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: */