Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / scaddins / source / pricing / pricing.cxx
blob772f1e36626ac0093c05ce859cae0aa9a1679f5b
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 static uno::Reference< uno::XInterface > xInst = (cppu::OWeakObject*) new ScaPricingAddIn();
175 return xInst;
179 extern "C" {
181 SAL_DLLPUBLIC_EXPORT void * SAL_CALL pricing_component_getFactory(
182 const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
184 void* pRet = 0;
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() ) );
195 if (xFactory.is())
197 xFactory->acquire();
198 pRet = xFactory.get();
202 return pRet;
205 } // extern C
207 // "normal" service implementation
208 ScaPricingAddIn::ScaPricingAddIn() :
209 pDefLocales( NULL ),
210 pResMgr( NULL ),
211 pFuncDataList( NULL )
215 ScaPricingAddIn::~ScaPricingAddIn()
217 if( pFuncDataList )
218 delete pFuncDataList;
219 if( pDefLocales )
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 )
242 if( !pDefLocales )
243 InitDefLocales();
245 return (nIndex < sizeof( pLang )) ? pDefLocales[ nIndex ] : aFuncLoc;
248 ResMgr& ScaPricingAddIn::GetResMgr() throw( uno::RuntimeException )
250 if( !pResMgr )
252 InitData(); // try to get resource manager
253 if( !pResMgr )
254 throw uno::RuntimeException();
256 return *pResMgr;
259 void ScaPricingAddIn::InitData()
262 if( pResMgr )
263 delete pResMgr;
265 OString aModName( "pricing" );
266 pResMgr = ResMgr::CreateResMgr( aModName.getStr(), LanguageTag( aFuncLoc) );
268 if( pFuncDataList )
269 delete pFuncDataList;
271 pFuncDataList = pResMgr ? new ScaFuncDataList( *pResMgr ) : NULL;
273 if( pDefLocales )
275 delete pDefLocales;
276 pDefLocales = 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 )
287 OUString aRet;
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();
297 return aRet;
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 );
311 return aRet;
314 // XServiceName
315 OUString SAL_CALL ScaPricingAddIn::getServiceName() throw( uno::RuntimeException, std::exception )
317 // name of specific AddIn service
318 return OUString( MY_SERVICE );
321 // XServiceInfo
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();
337 // XLocalizable
338 void SAL_CALL ScaPricingAddIn::setLocale( const lang::Locale& eLocale ) throw( uno::RuntimeException, std::exception )
340 aFuncLoc = eLocale;
341 InitData(); // change of locale invalidates resources!
344 lang::Locale SAL_CALL ScaPricingAddIn::getLocale() throw( uno::RuntimeException, std::exception )
346 return aFuncLoc;
349 // function descriptions start here
350 // XAddIn
351 OUString SAL_CALL ScaPricingAddIn::getProgrammaticFuntionName( const OUString& ) throw( uno::RuntimeException, std::exception )
353 // not used by calc
354 // (but should be implemented for other uses of the AddIn service)
355 return OUString();
358 OUString SAL_CALL ScaPricingAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
360 OUString aRet;
362 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
363 if( pFData )
365 aRet = GetDisplFuncStr( pFData->GetUINameID() );
366 if( pFData->IsDouble() )
367 aRet += STR_FROM_ANSI( "_ADD" );
369 else
371 aRet = STR_FROM_ANSI( "UNKNOWNFUNC_" );
372 aRet += aProgrammaticName;
375 return aRet;
378 OUString SAL_CALL ScaPricingAddIn::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
380 OUString aRet;
382 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
383 if( pFData )
384 aRet = GetFuncDescrStr( pFData->GetDescrID(), 1 );
386 return aRet;
389 OUString SAL_CALL ScaPricingAddIn::getDisplayArgumentName(
390 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
392 OUString aRet;
394 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
395 if( pFData && (nArgument <= 0xFFFF) )
397 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
398 if( nStr )
399 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr );
400 else
401 aRet = STR_FROM_ANSI( "internal" );
404 return aRet;
407 OUString SAL_CALL ScaPricingAddIn::getArgumentDescription(
408 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
410 OUString aRet;
412 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
413 if( pFData && (nArgument <= 0xFFFF) )
415 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
416 if( nStr )
417 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr + 1 );
418 else
419 aRet = STR_FROM_ANSI( "for internal use only" );
422 return aRet;
425 OUString SAL_CALL ScaPricingAddIn::getProgrammaticCategoryName(
426 const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
428 OUString aRet;
430 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
431 if( pFData )
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
442 break;
446 if( aRet.isEmpty() )
447 aRet = STR_FROM_ANSI( "Add-In" );
448 return aRet;
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 );
462 if( !pFData )
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 ) );
474 return aRet;
477 // actual function implementation starts here
478 // auxillary input handling functions
479 namespace {
481 bool getinput_putcall(bs::types::PutCall& pc, const OUString& str) {
482 if(str.startsWith("c")) {
483 pc=bs::types::Call;
484 } else if(str.startsWith("p")) {
485 pc=bs::types::Put;
486 } else {
487 return false;
489 return true;
492 bool getinput_putcall(bs::types::PutCall& pc, const uno::Any& anyval) {
493 OUString str;
494 if(anyval.getValueTypeClass() == uno::TypeClass_STRING) {
495 anyval >>= str;
496 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
497 str="c"; // call as default
498 } else {
499 return false;
501 return getinput_putcall(pc, str);
504 bool getinput_strike(double& strike, const uno::Any& anyval) {
505 if(anyval.getValueTypeClass() == uno::TypeClass_DOUBLE) {
506 anyval >>= strike;
507 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
508 strike=-1.0; // -1 as default (means not set)
509 } else {
510 return false;
512 return true;
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;
520 } else {
521 return false;
523 return true;
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;
531 } else {
532 return false;
534 return true;
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;
542 } else {
543 return false;
545 return true;
548 bool getinput_greek(bs::types::Greeks& greek, const uno::Any& anyval) {
549 OUString str;
550 if(anyval.getValueTypeClass() == uno::TypeClass_STRING) {
551 anyval >>= str;
552 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
553 str="value";
554 } else {
555 return false;
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;
577 } else {
578 return false;
580 return true;
583 } // namespace for auxillary functions
585 // OPT_BARRIER(...)
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 );
611 // OPT_TOUCH(...)
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,
632 fd,kio,bcont,greek);
634 RETURN_FINITE( fRet );
637 // OPT_PRB_HIT(...)
638 double SAL_CALL ScaPricingAddIn::getOptProbHit( double spot, double vol,
639 double mu, double T,
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,
654 double mu, double T,
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;
659 double K;
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: */