tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / scaddins / source / pricing / pricing.cxx
blob2ca1a2cfd581b599ea4b48e05730032a8784ef83
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>
28 #include <strings.hrc>
30 #include <cppuhelper/factory.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <cppuhelper/weak.hxx>
33 #include <algorithm>
34 #include <cmath>
35 #include <string_view>
36 #include <unotools/resmgr.hxx>
37 #include <i18nlangtag/languagetag.hxx>
38 #include <o3tl/string_view.hxx>
40 using namespace ::com::sun::star;
41 using namespace sca::pricing;
44 constexpr OUString ADDIN_SERVICE = u"com.sun.star.sheet.AddIn"_ustr;
45 constexpr OUString MY_SERVICE = u"com.sun.star.sheet.addin.PricingFunctions"_ustr;
46 constexpr OUStringLiteral MY_IMPLNAME = u"com.sun.star.sheet.addin.PricingFunctionsImpl";
48 const ScaFuncDataBase pFuncDataArr[] =
50 { "getOptBarrier", PRICING_FUNCNAME_OptBarrier, PRICING_FUNCDESC_OptBarrier, "OPT_BARRIER", 13, ScaCategory::Finance, false, false },
51 { "getOptTouch", PRICING_FUNCNAME_OptTouch, PRICING_FUNCDESC_OptTouch, "OPT_TOUCH", 11, ScaCategory::Finance, false, false },
52 { "getOptProbHit", PRICING_FUNCNAME_OptProbHit, PRICING_FUNCDESC_OptProbHit, "OPT_PROB_HIT", 6, ScaCategory::Finance, false, false },
53 { "getOptProbInMoney", PRICING_FUNCNAME_OptProbInMoney, PRICING_FUNCDESC_OptProbInMoney, "OPT_PROB_INMONEY", 8, ScaCategory::Finance, false, false },
56 ScaFuncData::ScaFuncData( const ScaFuncDataBase& rBaseData ) :
57 aIntName( OUString::createFromAscii( rBaseData.pIntName ) ),
58 pUINameID( rBaseData.pUINameID ),
59 pDescrID( rBaseData.pDescrID ),
60 nParamCount( rBaseData.nParamCount ),
61 eCat( rBaseData.eCat ),
62 bDouble( rBaseData.bDouble ),
63 bWithOpt( rBaseData.bWithOpt )
65 aCompList.push_back(OUString::createFromAscii(rBaseData.pCompName));
68 sal_uInt16 ScaFuncData::GetStrIndex( sal_uInt16 nParam ) const
70 if( !bWithOpt )
71 nParam++;
72 return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
75 void sca::pricing::InitScaFuncDataList(ScaFuncDataList& rList)
77 for (const auto & nIndex : pFuncDataArr)
78 rList.emplace_back(nIndex);
81 // entry points for service registration / instantiation
83 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
84 scaddins_ScaPricingAddIn_get_implementation(
85 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
87 return cppu::acquire(new ScaPricingAddIn());
90 // "normal" service implementation
91 ScaPricingAddIn::ScaPricingAddIn()
95 ScaPricingAddIn::~ScaPricingAddIn()
99 static const char* pLang[] = { "en" };
100 static const char* pCoun[] = { "US" };
101 constexpr sal_uInt32 nNumOfLoc = std::size( pLang );
103 void ScaPricingAddIn::InitDefLocales()
105 pDefLocales.reset( new lang::Locale[ nNumOfLoc ] );
107 for( sal_uInt32 nIndex = 0; nIndex < nNumOfLoc; nIndex++ )
109 pDefLocales[ nIndex ].Language = OUString::createFromAscii( pLang[ nIndex ] );
110 pDefLocales[ nIndex ].Country = OUString::createFromAscii( pCoun[ nIndex ] );
114 const lang::Locale& ScaPricingAddIn::GetLocale( sal_uInt32 nIndex )
116 if( !pDefLocales )
117 InitDefLocales();
119 return (nIndex < nNumOfLoc) ? pDefLocales[ nIndex ] : aFuncLoc;
122 void ScaPricingAddIn::InitData()
124 aResLocale = Translate::Create("sca", LanguageTag(aFuncLoc));
125 pFuncDataList.reset(new ScaFuncDataList);
126 InitScaFuncDataList(*pFuncDataList);
127 pDefLocales.reset();
130 OUString ScaPricingAddIn::GetFuncDescrStr(const TranslateId* pResId, sal_uInt16 nStrIndex)
132 return ScaResId(pResId[nStrIndex - 1]);
135 // XServiceName
136 OUString SAL_CALL ScaPricingAddIn::getServiceName()
138 // name of specific AddIn service
139 return MY_SERVICE;
142 // XServiceInfo
143 OUString SAL_CALL ScaPricingAddIn::getImplementationName()
145 return MY_IMPLNAME;
148 sal_Bool SAL_CALL ScaPricingAddIn::supportsService( const OUString& aServiceName )
150 return cppu::supportsService(this, aServiceName);
153 uno::Sequence< OUString > SAL_CALL ScaPricingAddIn::getSupportedServiceNames()
155 return { ADDIN_SERVICE, MY_SERVICE };
158 // XLocalizable
159 void SAL_CALL ScaPricingAddIn::setLocale( const lang::Locale& eLocale )
161 aFuncLoc = eLocale;
162 InitData(); // change of locale invalidates resources!
165 lang::Locale SAL_CALL ScaPricingAddIn::getLocale()
167 return aFuncLoc;
170 // function descriptions start here
171 // XAddIn
172 OUString SAL_CALL ScaPricingAddIn::getProgrammaticFuntionName( const OUString& )
174 // not used by calc
175 // (but should be implemented for other uses of the AddIn service)
176 return OUString();
179 OUString SAL_CALL ScaPricingAddIn::getDisplayFunctionName( const OUString& aProgrammaticName )
181 OUString aRet;
183 auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(),
184 FindScaFuncData( aProgrammaticName ) );
185 if (fDataIt != pFuncDataList->end() )
187 aRet = ScaResId(fDataIt->GetUINameID());
188 if( fDataIt->IsDouble() )
189 aRet += "_ADD";
191 else
193 aRet = "UNKNOWNFUNC_" + aProgrammaticName;
196 return aRet;
199 OUString SAL_CALL ScaPricingAddIn::getFunctionDescription( const OUString& aProgrammaticName )
201 OUString aRet;
203 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
204 FindScaFuncData( aProgrammaticName ) );
205 if( fDataIt != pFuncDataList->end() )
206 aRet = GetFuncDescrStr( fDataIt->GetDescrID(), 1 );
208 return aRet;
211 OUString SAL_CALL ScaPricingAddIn::getDisplayArgumentName(
212 const OUString& aProgrammaticName, sal_Int32 nArgument )
214 OUString aRet;
216 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
217 FindScaFuncData( aProgrammaticName ) );
218 if( fDataIt != pFuncDataList->end() && (nArgument <= 0xFFFF) )
220 sal_uInt16 nStr = fDataIt->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
221 if( nStr )
222 aRet = GetFuncDescrStr( fDataIt->GetDescrID(), nStr );
223 else
224 aRet = "internal";
227 return aRet;
230 OUString SAL_CALL ScaPricingAddIn::getArgumentDescription(
231 const OUString& aProgrammaticName, sal_Int32 nArgument )
233 OUString aRet;
235 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
236 FindScaFuncData( aProgrammaticName ) );
237 if( fDataIt != pFuncDataList->end() && (nArgument <= 0xFFFF) )
239 sal_uInt16 nStr = fDataIt->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
240 if( nStr )
241 aRet = GetFuncDescrStr( fDataIt->GetDescrID(), nStr + 1 );
242 else
243 aRet = "for internal use only";
246 return aRet;
249 OUString SAL_CALL ScaPricingAddIn::getProgrammaticCategoryName(
250 const OUString& aProgrammaticName )
252 OUString aRet;
254 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
255 FindScaFuncData( aProgrammaticName ) );
256 if( fDataIt != pFuncDataList->end() )
258 switch( fDataIt->GetCategory() )
260 case ScaCategory::DateTime: aRet = "Date&Time"; break;
261 case ScaCategory::Text: aRet = "Text"; break;
262 case ScaCategory::Finance: aRet = "Financial"; break;
263 case ScaCategory::Inf: aRet = "Information"; break;
264 case ScaCategory::Math: aRet = "Mathematical"; break;
265 case ScaCategory::Tech: aRet = "Technical"; break;
269 if( aRet.isEmpty() )
270 aRet = "Add-In";
271 return aRet;
274 OUString SAL_CALL ScaPricingAddIn::getDisplayCategoryName(
275 const OUString& aProgrammaticName )
277 return getProgrammaticCategoryName( aProgrammaticName );
280 // XCompatibilityNames
281 uno::Sequence< sheet::LocalizedName > SAL_CALL ScaPricingAddIn::getCompatibilityNames(
282 const OUString& aProgrammaticName )
284 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
285 FindScaFuncData( aProgrammaticName ) );
286 if( fDataIt == pFuncDataList->end() )
287 return uno::Sequence< sheet::LocalizedName >( 0 );
289 const std::vector<OUString>& rStrList = fDataIt->GetCompNameList();
290 sal_uInt32 nCount = rStrList.size();
292 uno::Sequence< sheet::LocalizedName > aRet( nCount );
293 sheet::LocalizedName* pArray = aRet.getArray();
295 for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
296 pArray[ nIndex ] = sheet::LocalizedName( GetLocale( nIndex ), rStrList[nIndex] );
298 return aRet;
301 // actual function implementation starts here
302 // auxiliary input handling functions
303 namespace {
305 bool getinput_putcall(bs::types::PutCall& pc, std::u16string_view str) {
306 if(o3tl::starts_with(str, u"c")) {
307 pc=bs::types::Call;
308 } else if(o3tl::starts_with(str, u"p")) {
309 pc=bs::types::Put;
310 } else {
311 return false;
313 return true;
316 bool getinput_putcall(bs::types::PutCall& pc, const uno::Any& anyval) {
317 OUString str;
318 if(anyval.getValueTypeClass() == uno::TypeClass_STRING) {
319 anyval >>= str;
320 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
321 str="c"; // call as default
322 } else {
323 return false;
325 return getinput_putcall(pc, str);
328 bool getinput_strike(double& strike, const uno::Any& anyval) {
329 if(anyval.getValueTypeClass() == uno::TypeClass_DOUBLE) {
330 anyval >>= strike;
331 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
332 strike=-1.0; // -1 as default (means not set)
333 } else {
334 return false;
336 return true;
339 bool getinput_inout(bs::types::BarrierKIO& kio, std::u16string_view str) {
340 if(o3tl::starts_with(str, u"i")) {
341 kio=bs::types::KnockIn;
342 } else if(o3tl::starts_with(str, u"o")) {
343 kio=bs::types::KnockOut;
344 } else {
345 return false;
347 return true;
350 bool getinput_barrier(bs::types::BarrierActive& cont, std::u16string_view str) {
351 if(o3tl::starts_with(str, u"c")) {
352 cont=bs::types::Continuous;
353 } else if(o3tl::starts_with(str, u"e")) {
354 cont=bs::types::Maturity;
355 } else {
356 return false;
358 return true;
361 bool getinput_fordom(bs::types::ForDom& fd, std::u16string_view str) {
362 if(o3tl::starts_with(str, u"f")) {
363 fd=bs::types::Foreign;
364 } else if(o3tl::starts_with(str, u"d")) {
365 fd=bs::types::Domestic;
366 } else {
367 return false;
369 return true;
372 bool getinput_greek(bs::types::Greeks& greek, const uno::Any& anyval) {
373 OUString str;
374 if(anyval.getValueTypeClass() == uno::TypeClass_STRING) {
375 anyval >>= str;
376 } else if(anyval.getValueTypeClass() == uno::TypeClass_VOID) {
377 str="value";
378 } else {
379 return false;
382 if(str == "value" || str == "price" || str == "v" || str == "p") {
383 greek=bs::types::Value;
384 } else if(str == "delta" || str == "d") {
385 greek=bs::types::Delta;
386 } else if(str == "gamma" || str == "g") {
387 greek=bs::types::Gamma;
388 } else if(str == "theta" || str == "t") {
389 greek=bs::types::Theta;
390 } else if(str == "vega" || str == "e") {
391 greek=bs::types::Vega;
392 } else if(str == "volga" || str == "o") {
393 greek=bs::types::Volga;
394 } else if(str == "vanna" || str == "a") {
395 greek=bs::types::Vanna;
396 } else if(str == "rho" || str == "r") {
397 greek=bs::types::Rho_d;
398 } else if(str == "rhof" || str == "f") {
399 greek=bs::types::Rho_f;
400 } else {
401 return false;
403 return true;
406 } // namespace for auxiliary functions
408 // OPT_BARRIER(...)
409 double SAL_CALL ScaPricingAddIn::getOptBarrier( double spot, double vol,
410 double r, double rf, double T, double strike,
411 double barrier_low, double barrier_up, double rebate,
412 const OUString& put_call, const OUString& in_out,
413 const OUString& barriercont, const uno::Any& greekstr )
415 bs::types::PutCall pc;
416 bs::types::BarrierKIO kio;
417 bs::types::BarrierActive bcont;
418 bs::types::Greeks greek;
419 // read and check input values
420 if( spot<=0.0 || vol<=0.0 || T<0.0 || strike<0.0 ||
421 !getinput_putcall(pc,put_call) ||
422 !getinput_inout(kio,in_out) ||
423 !getinput_barrier(bcont,barriercont) ||
424 !getinput_greek(greek,greekstr) ){
425 throw lang::IllegalArgumentException();
428 double fRet=bs::barrier(spot,vol,r,rf,T,strike, barrier_low,barrier_up,
429 rebate,pc,kio,bcont,greek);
431 if (!std::isfinite(fRet))
432 throw css::lang::IllegalArgumentException();
433 return fRet;
436 // OPT_TOUCH(...)
437 double SAL_CALL ScaPricingAddIn::getOptTouch( double spot, double vol,
438 double r, double rf, double T,
439 double barrier_low, double barrier_up,
440 const OUString& for_dom, const OUString& in_out,
441 const OUString& barriercont, const uno::Any& greekstr )
443 bs::types::ForDom fd;
444 bs::types::BarrierKIO kio;
445 bs::types::BarrierActive bcont;
446 bs::types::Greeks greek;
447 // read and check input values
448 if( spot<=0.0 || vol<=0.0 || T<0.0 ||
449 !getinput_fordom(fd,for_dom) ||
450 !getinput_inout(kio,in_out) ||
451 !getinput_barrier(bcont,barriercont) ||
452 !getinput_greek(greek,greekstr) ){
453 throw lang::IllegalArgumentException();
456 double fRet=bs::touch(spot,vol,r,rf,T,barrier_low,barrier_up,
457 fd,kio,bcont,greek);
459 if (!std::isfinite(fRet))
460 throw css::lang::IllegalArgumentException();
461 return fRet;
464 // OPT_PRB_HIT(...)
465 double SAL_CALL ScaPricingAddIn::getOptProbHit( double spot, double vol,
466 double mu, double T,
467 double barrier_low, double barrier_up )
469 // read and check input values
470 if( spot<=0.0 || vol<=0.0 || T<0.0 ) {
471 throw lang::IllegalArgumentException();
474 double fRet=bs::prob_hit(spot,vol,mu,T,barrier_low,barrier_up);
476 if (!std::isfinite(fRet))
477 throw css::lang::IllegalArgumentException();
478 return fRet;
481 // OPT_PROB_INMONEY(...)
482 double SAL_CALL ScaPricingAddIn::getOptProbInMoney( double spot, double vol,
483 double mu, double T,
484 double barrier_low, double barrier_up,
485 const uno::Any& strikeval, const uno::Any& put_call )
487 bs::types::PutCall pc=bs::types::Call;
488 double K = 0;
490 // read and check input values
491 if( spot<=0.0 || vol<=0.0 || T<0.0 ||
492 !getinput_putcall(pc,put_call) ||
493 !getinput_strike(K,strikeval) ) {
494 throw lang::IllegalArgumentException();
497 double fRet=bs::prob_in_money(spot,vol,mu,T,K,barrier_low,barrier_up,pc);
499 if (!std::isfinite(fRet))
500 throw css::lang::IllegalArgumentException();
501 return fRet;
504 OUString ScaPricingAddIn::ScaResId(TranslateId aResId)
506 return Translate::get(aResId, aResLocale);
509 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */