LibreOffice Module scaddins (master) 1
pricing.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20// pricing functions add in
21
22// all of the UNO add-in technical details have been copied from
23// ../datefunc/datefunc.cxx
24
25#include "pricing.hxx"
26#include "black_scholes.hxx"
27#include <pricing.hrc>
28#include <strings.hrc>
29
32#include <cppuhelper/weak.hxx>
33#include <algorithm>
34#include <cmath>
35#include <string_view>
36#include <unotools/resmgr.hxx>
38#include <o3tl/string_view.hxx>
39
40using namespace ::com::sun::star;
41using namespace sca::pricing;
42
43
44constexpr OUStringLiteral ADDIN_SERVICE = u"com.sun.star.sheet.AddIn";
45constexpr OUStringLiteral MY_SERVICE = u"com.sun.star.sheet.addin.PricingFunctions";
46constexpr OUStringLiteral MY_IMPLNAME = u"com.sun.star.sheet.addin.PricingFunctionsImpl";
47
49{
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 },
54};
55
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 )
64{
65 aCompList.push_back(OUString::createFromAscii(rBaseData.pCompName));
66}
67
68sal_uInt16 ScaFuncData::GetStrIndex( sal_uInt16 nParam ) const
69{
70 if( !bWithOpt )
71 nParam++;
72 return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
73}
74
76{
77 for (const auto & nIndex : pFuncDataArr)
78 rList.push_back(ScaFuncData(nIndex));
79}
80
81// entry points for service registration / instantiation
82
83extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
85 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
86{
87 return cppu::acquire(new ScaPricingAddIn());
88}
89
90// "normal" service implementation
92{
93}
94
96{
97}
98
99static const char* pLang[] = { "en" };
100static const char* pCoun[] = { "US" };
101const sal_uInt32 nNumOfLoc = SAL_N_ELEMENTS( pLang );
102
104{
105 pDefLocales.reset( new lang::Locale[ nNumOfLoc ] );
106
107 for( sal_uInt32 nIndex = 0; nIndex < nNumOfLoc; nIndex++ )
108 {
109 pDefLocales[ nIndex ].Language = OUString::createFromAscii( pLang[ nIndex ] );
110 pDefLocales[ nIndex ].Country = OUString::createFromAscii( pCoun[ nIndex ] );
111 }
112}
113
114const lang::Locale& ScaPricingAddIn::GetLocale( sal_uInt32 nIndex )
115{
116 if( !pDefLocales )
117 InitDefLocales();
118
119 return (nIndex < nNumOfLoc) ? pDefLocales[ nIndex ] : aFuncLoc;
120}
121
123{
124 aResLocale = Translate::Create("sca", LanguageTag(aFuncLoc));
125 pFuncDataList.reset(new ScaFuncDataList);
126 InitScaFuncDataList(*pFuncDataList);
127 pDefLocales.reset();
128}
129
130OUString ScaPricingAddIn::GetFuncDescrStr(const TranslateId* pResId, sal_uInt16 nStrIndex)
131{
132 return ScaResId(pResId[nStrIndex - 1]);
133}
134
135// XServiceName
137{
138 // name of specific AddIn service
139 return MY_SERVICE;
140}
141
142// XServiceInfo
144{
145 return MY_IMPLNAME;
146}
147
148sal_Bool SAL_CALL ScaPricingAddIn::supportsService( const OUString& aServiceName )
149{
150 return cppu::supportsService(this, aServiceName);
151}
152
153uno::Sequence< OUString > SAL_CALL ScaPricingAddIn::getSupportedServiceNames()
154{
155 return { ADDIN_SERVICE, MY_SERVICE };
156}
157
158// XLocalizable
159void SAL_CALL ScaPricingAddIn::setLocale( const lang::Locale& eLocale )
160{
161 aFuncLoc = eLocale;
162 InitData(); // change of locale invalidates resources!
163}
164
165lang::Locale SAL_CALL ScaPricingAddIn::getLocale()
166{
167 return aFuncLoc;
168}
169
170// function descriptions start here
171// XAddIn
172OUString SAL_CALL ScaPricingAddIn::getProgrammaticFuntionName( const OUString& )
173{
174 // not used by calc
175 // (but should be implemented for other uses of the AddIn service)
176 return OUString();
177}
178
179OUString SAL_CALL ScaPricingAddIn::getDisplayFunctionName( const OUString& aProgrammaticName )
180{
181 OUString aRet;
182
183 auto fDataIt = std::find_if(pFuncDataList->begin(), pFuncDataList->end(),
184 FindScaFuncData( aProgrammaticName ) );
185 if (fDataIt != pFuncDataList->end() )
186 {
187 aRet = ScaResId(fDataIt->GetUINameID());
188 if( fDataIt->IsDouble() )
189 aRet += "_ADD";
190 }
191 else
192 {
193 aRet = "UNKNOWNFUNC_" + aProgrammaticName;
194 }
195
196 return aRet;
197}
198
199OUString SAL_CALL ScaPricingAddIn::getFunctionDescription( const OUString& aProgrammaticName )
200{
201 OUString aRet;
202
203 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
204 FindScaFuncData( aProgrammaticName ) );
205 if( fDataIt != pFuncDataList->end() )
206 aRet = GetFuncDescrStr( fDataIt->GetDescrID(), 1 );
207
208 return aRet;
209}
210
212 const OUString& aProgrammaticName, sal_Int32 nArgument )
213{
214 OUString aRet;
215
216 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
217 FindScaFuncData( aProgrammaticName ) );
218 if( fDataIt != pFuncDataList->end() && (nArgument <= 0xFFFF) )
219 {
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";
225 }
226
227 return aRet;
228}
229
231 const OUString& aProgrammaticName, sal_Int32 nArgument )
232{
233 OUString aRet;
234
235 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
236 FindScaFuncData( aProgrammaticName ) );
237 if( fDataIt != pFuncDataList->end() && (nArgument <= 0xFFFF) )
238 {
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";
244 }
245
246 return aRet;
247}
248
250 const OUString& aProgrammaticName )
251{
252 OUString aRet;
253
254 auto fDataIt = std::find_if( pFuncDataList->begin(), pFuncDataList->end(),
255 FindScaFuncData( aProgrammaticName ) );
256 if( fDataIt != pFuncDataList->end() )
257 {
258 switch( fDataIt->GetCategory() )
259 {
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;
266 }
267 }
268
269 if( aRet.isEmpty() )
270 aRet = "Add-In";
271 return aRet;
272}
273
275 const OUString& aProgrammaticName )
276{
277 return getProgrammaticCategoryName( aProgrammaticName );
278}
279
280// XCompatibilityNames
281uno::Sequence< sheet::LocalizedName > SAL_CALL ScaPricingAddIn::getCompatibilityNames(
282 const OUString& aProgrammaticName )
283{
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 );
288
289 const std::vector<OUString>& rStrList = fDataIt->GetCompNameList();
290 sal_uInt32 nCount = rStrList.size();
291
292 uno::Sequence< sheet::LocalizedName > aRet( nCount );
293 sheet::LocalizedName* pArray = aRet.getArray();
294
295 for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
296 pArray[ nIndex ] = sheet::LocalizedName( GetLocale( nIndex ), rStrList[nIndex] );
297
298 return aRet;
299}
300
301// actual function implementation starts here
302// auxiliary input handling functions
303namespace {
304
305bool getinput_putcall(bs::types::PutCall& pc, std::u16string_view str) {
306 if(o3tl::starts_with(str, u"c")) {
308 } else if(o3tl::starts_with(str, u"p")) {
310 } else {
311 return false;
312 }
313 return true;
314}
315
316bool 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;
324 }
325 return getinput_putcall(pc, str);
326}
327
328bool 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;
335 }
336 return true;
337}
338
339bool getinput_inout(bs::types::BarrierKIO& kio, std::u16string_view str) {
340 if(o3tl::starts_with(str, u"i")) {
342 } else if(o3tl::starts_with(str, u"o")) {
344 } else {
345 return false;
346 }
347 return true;
348}
349
350bool getinput_barrier(bs::types::BarrierActive& cont, std::u16string_view str) {
351 if(o3tl::starts_with(str, u"c")) {
353 } else if(o3tl::starts_with(str, u"e")) {
355 } else {
356 return false;
357 }
358 return true;
359}
360
361bool getinput_fordom(bs::types::ForDom& fd, std::u16string_view str) {
362 if(o3tl::starts_with(str, u"f")) {
364 } else if(o3tl::starts_with(str, u"d")) {
366 } else {
367 return false;
368 }
369 return true;
370}
371
372bool 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;
380 }
381
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;
402 }
403 return true;
404}
405
406} // namespace for auxiliary functions
407
408// OPT_BARRIER(...)
409double 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 )
414{
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();
426 }
427
428 double fRet=bs::barrier(spot,vol,r,rf,T,strike, barrier_low,barrier_up,
429 rebate,pc,kio,bcont,greek);
430
431 if (!std::isfinite(fRet))
432 throw css::lang::IllegalArgumentException();
433 return fRet;
434}
435
436// OPT_TOUCH(...)
437double 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 )
442{
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();
454 }
455
456 double fRet=bs::touch(spot,vol,r,rf,T,barrier_low,barrier_up,
457 fd,kio,bcont,greek);
458
459 if (!std::isfinite(fRet))
460 throw css::lang::IllegalArgumentException();
461 return fRet;
462}
463
464// OPT_PRB_HIT(...)
465double SAL_CALL ScaPricingAddIn::getOptProbHit( double spot, double vol,
466 double mu, double T,
467 double barrier_low, double barrier_up )
468{
469 // read and check input values
470 if( spot<=0.0 || vol<=0.0 || T<0.0 ) {
471 throw lang::IllegalArgumentException();
472 }
473
474 double fRet=bs::prob_hit(spot,vol,mu,T,barrier_low,barrier_up);
475
476 if (!std::isfinite(fRet))
477 throw css::lang::IllegalArgumentException();
478 return fRet;
479}
480
481// OPT_PROB_INMONEY(...)
482double 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 )
486{
488 double K = 0;
489
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();
495 }
496
497 double fRet=bs::prob_in_money(spot,vol,mu,T,K,barrier_low,barrier_up,pc);
498
499 if (!std::isfinite(fRet))
500 throw css::lang::IllegalArgumentException();
501 return fRet;
502}
503
505{
506 return Translate::get(aResId, aResLocale);
507}
508
509/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScaFuncData(const ScaFuncDataBase &rBaseData)
Definition: datefunc.cxx:62
virtual css::uno::Sequence< css::sheet::LocalizedName > SAL_CALL getCompatibilityNames(const OUString &aProgrammaticName) override
Definition: pricing.cxx:281
virtual OUString SAL_CALL getImplementationName() override
Definition: pricing.cxx:143
void InitDefLocales()
Definition: pricing.cxx:103
virtual OUString SAL_CALL getProgrammaticFuntionName(const OUString &aDisplayName) override
Definition: pricing.cxx:172
virtual OUString SAL_CALL getProgrammaticCategoryName(const OUString &aProgrammaticName) override
Definition: pricing.cxx:249
virtual OUString SAL_CALL getFunctionDescription(const OUString &aProgrammaticName) override
Definition: pricing.cxx:199
virtual OUString SAL_CALL getDisplayFunctionName(const OUString &aProgrammaticName) override
Definition: pricing.cxx:179
virtual double SAL_CALL getOptBarrier(double spot, double vol, double r, double rf, double T, double strike, double barrier_low, double barrier_up, double rebate, const OUString &put_call, const OUString &in_out, const OUString &continuous, const css::uno::Any &greek) override
Definition: pricing.cxx:409
virtual OUString SAL_CALL getDisplayCategoryName(const OUString &aProgrammaticName) override
Definition: pricing.cxx:274
OUString GetFuncDescrStr(const TranslateId *pResId, sal_uInt16 nStrIndex)
Definition: pricing.cxx:130
virtual double SAL_CALL getOptTouch(double spot, double vol, double r, double rf, double T, double barrier_low, double barrier_up, const OUString &for_dom, const OUString &in_out, const OUString &barriercont, const css::uno::Any &greekstr) override
Definition: pricing.cxx:437
virtual OUString SAL_CALL getServiceName() override
Definition: pricing.cxx:136
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: pricing.cxx:148
virtual double SAL_CALL getOptProbHit(double spot, double vol, double mu, double T, double barrier_low, double barrier_up) override
Definition: pricing.cxx:465
virtual OUString SAL_CALL getDisplayArgumentName(const OUString &aProgrammaticName, sal_Int32 nArgument) override
Definition: pricing.cxx:211
const css::lang::Locale & GetLocale(sal_uInt32 nIndex)
Definition: pricing.cxx:114
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: pricing.cxx:153
virtual OUString SAL_CALL getArgumentDescription(const OUString &aProgrammaticName, sal_Int32 nArgument) override
Definition: pricing.cxx:230
virtual css::lang::Locale SAL_CALL getLocale() override
Definition: pricing.cxx:165
OUString ScaResId(TranslateId aResId)
Definition: pricing.cxx:504
virtual ~ScaPricingAddIn() override
Definition: pricing.cxx:95
virtual double SAL_CALL getOptProbInMoney(double spot, double vol, double mu, double T, double barrier_low, double barrier_up, const css::uno::Any &strikeval, const css::uno::Any &put_call) override
Definition: pricing.cxx:482
virtual void SAL_CALL setLocale(const css::lang::Locale &eLocale) override
Definition: pricing.cxx:159
void InitData()
Definition: pricing.cxx:122
std::vector< OUString > aCompList
Definition: pricing.hxx:79
sal_uInt16 GetStrIndex(sal_uInt16 nParam) const
Definition: pricing.cxx:68
int nCount
std::vector< ScaFuncData > ScaFuncDataList
Definition: datefunc.hxx:86
float u
sal_Int32 nIndex
#define SAL_N_ELEMENTS(arr)
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString get(TranslateId sContextAndId, const std::locale &loc)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
double touch(double S, double vol, double rd, double rf, double tau, double B1, double B2, types::ForDom fd, types::BarrierKIO kio, types::BarrierActive bcont, types::Greeks greek)
double prob_in_money(double S, double vol, double mu, double tau, double B1, double B2)
double barrier(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, double rebate, types::PutCall pc, types::BarrierKIO kio, types::BarrierActive bcont, types::Greeks greek)
double prob_hit(double S, double vol, double mu, double tau, double B1, double B2)
std::vector< ScaFuncData > ScaFuncDataList
Definition: pricing.hxx:100
void InitScaFuncDataList(ScaFuncDataList &rMap)
Definition: pricing.cxx:75
const ScaFuncDataBase pFuncDataArr[]
Definition: pricing.cxx:48
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * scaddins_ScaPricingAddIn_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: pricing.cxx:84
static const char * pCoun[]
Definition: pricing.cxx:100
const sal_uInt32 nNumOfLoc
Definition: pricing.cxx:101
constexpr OUStringLiteral MY_IMPLNAME
Definition: pricing.cxx:46
static const char * pLang[]
Definition: pricing.cxx:99
constexpr OUStringLiteral ADDIN_SERVICE
Definition: pricing.cxx:44
constexpr OUStringLiteral MY_SERVICE
Definition: pricing.cxx:45
unsigned char sal_Bool