1
/* This file is part of the KDE project
2
Copyright (C) 1998-2002 The KSpread Team
3
www.koffice.org/kspread
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public License
16
along with this library; see the file COPYING.LIB. If not, write to
17
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
Boston, MA 02111-1307, USA.
21
// built-in financial functions
29
#include <koscript_parser.h>
30
#include <koscript_util.h>
31
#include <koscript_func.h>
32
#include <koscript_synext.h>
34
#include <kspread_functions.h>
35
#include <kspread_functions_helper.h>
36
#include <kspread_util.h>
39
// prototypes (sorted)
40
bool kspreadfunc_accrint( KSContext& context );
41
bool kspreadfunc_accrintm( KSContext& context );
42
bool kspreadfunc_compound( KSContext& context );
43
bool kspreadfunc_continuous( KSContext& context );
44
bool kspreadfunc_coupnum( KSContext& context );
45
bool kspreadfunc_db( KSContext& context );
46
bool kspreadfunc_ddb( KSContext& context );
47
bool kspreadfunc_disc( KSContext& context );
48
bool kspreadfunc_dollarde( KSContext& context );
49
bool kspreadfunc_dollarfr( KSContext& context );
50
bool kspreadfunc_duration( KSContext& context );
51
bool kspreadfunc_effective( KSContext& context );
52
bool kspreadfunc_euro( KSContext& context );
53
bool kspreadfunc_fv( KSContext& context );
54
bool kspreadfunc_fv_annuity( KSContext& context );
55
bool kspreadfunc_intrate( KSContext& context );
56
bool kspreadfunc_ipmt( KSContext& context );
57
bool kspreadfunc_ispmt( KSContext& context );
58
bool kspreadfunc_level_coupon( KSContext& context );
59
bool kspreadfunc_nominal( KSContext& context );
60
bool kspreadfunc_nper( KSContext& context );
61
bool kspreadfunc_pmt( KSContext& context );
62
bool kspreadfunc_ppmt( KSContext& context );
63
bool kspreadfunc_pv( KSContext& context );
64
bool kspreadfunc_pv_annuity( KSContext& context );
65
bool kspreadfunc_received( KSContext& context );
66
bool kspreadfunc_sln( KSContext& context );
67
bool kspreadfunc_syd( KSContext& context );
68
bool kspreadfunc_tbilleq( KSContext& context );
69
bool kspreadfunc_tbillprice( KSContext& context );
70
bool kspreadfunc_tbillyield( KSContext& context );
71
bool kspreadfunc_zero_coupon( KSContext& context );
73
// registers all financial functions
74
void KSpreadRegisterFinancialFunctions()
76
KSpreadFunctionRepository* repo = KSpreadFunctionRepository::self();
78
repo->registerFunction( "ACCRINT", kspreadfunc_accrint );
79
repo->registerFunction( "ACCRINTM", kspreadfunc_accrintm );
80
repo->registerFunction( "COMPOUND", kspreadfunc_compound );
81
repo->registerFunction( "CONTINUOUS", kspreadfunc_continuous );
82
repo->registerFunction( "COUPNUM", kspreadfunc_coupnum );
83
repo->registerFunction( "DB", kspreadfunc_db );
84
repo->registerFunction( "DDB", kspreadfunc_ddb );
85
repo->registerFunction( "DISC", kspreadfunc_disc );
86
repo->registerFunction( "DOLLARDE", kspreadfunc_dollarde );
87
repo->registerFunction( "DOLLARFR", kspreadfunc_dollarfr );
88
repo->registerFunction( "DURATION", kspreadfunc_duration );
89
repo->registerFunction( "EFFECT", kspreadfunc_effective );
90
repo->registerFunction( "EFFECTIVE", kspreadfunc_effective );
91
repo->registerFunction( "EURO", kspreadfunc_euro ); // KSpread-specific, Gnumeric-compatible
92
repo->registerFunction( "FV", kspreadfunc_fv );
93
repo->registerFunction( "FV_ANNUITY", kspreadfunc_fv_annuity );
94
repo->registerFunction( "INTRATE", kspreadfunc_intrate );
95
repo->registerFunction( "IPMT", kspreadfunc_ipmt );
96
repo->registerFunction( "ISPMT", kspreadfunc_ispmt );
97
repo->registerFunction( "LEVEL_COUPON", kspreadfunc_level_coupon );
98
repo->registerFunction( "NOMINAL", kspreadfunc_nominal );
99
repo->registerFunction( "NPER", kspreadfunc_nper );
100
repo->registerFunction( "PMT", kspreadfunc_pmt );
101
repo->registerFunction( "PPMT", kspreadfunc_ppmt );
102
repo->registerFunction( "PV", kspreadfunc_pv );
103
repo->registerFunction( "PV_ANNUITY", kspreadfunc_pv_annuity );
104
repo->registerFunction( "RECEIVED", kspreadfunc_received );
105
repo->registerFunction( "SLN", kspreadfunc_sln );
106
repo->registerFunction( "SYD", kspreadfunc_syd );
107
repo->registerFunction( "TBILLEQ", kspreadfunc_tbilleq );
108
repo->registerFunction( "TBILLPRICE", kspreadfunc_tbillprice );
109
repo->registerFunction( "TBILLYIELD", kspreadfunc_tbillyield );
110
repo->registerFunction( "ZERO_COUPON", kspreadfunc_zero_coupon );
113
static double getPay( double rate, double nper, double pv, double fv, int type )
117
pvif = ( pow( 1 + rate, nper ) );
118
fvifa = ( pow( 1 + rate, nper ) - 1 ) / rate;
120
return ( ( -pv * pvif - fv ) / ( ( 1.0 + rate * type ) * fvifa ) );
123
static double getPrinc( double start, double pay,
124
double rate, double period )
126
return ( start * pow( 1.0 + rate, period) + pay
127
* ( ( pow( 1 + rate, period ) - 1 ) / rate ) );
130
static bool getCoupParameter( KSContext & context, QString const & fName, QDate & settlement,
131
QDate & maturity, int & frequency, int & basis, bool & eom )
133
QValueList<KSValue::Ptr> & args = context.value()->listValue();
135
if ( !KSUtil::checkArgumentsCount( context, 5, fName, true ) )
137
if ( !KSUtil::checkArgumentsCount( context, 4, fName, true ) )
139
if ( !KSUtil::checkArgumentsCount( context, 3, fName, true ) )
144
if ( !KSUtil::checkType( context, args[3], KSValue::IntType, true ) )
146
basis = args[3]->intValue();
151
if ( !KSUtil::checkType( context, args[3], KSValue::IntType, true ) )
153
if ( !KSUtil::checkType( context, args[4], KSValue::BoolType, true ) )
156
basis = args[3]->intValue();
157
eom = args[4]->boolValue();
160
if ( !getDate( context, args[0], settlement ) )
163
if ( !getDate( context, args[1], maturity ) )
166
if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
169
frequency = args[2]->intValue();
171
if (basis < 0 || basis > 5 || ( frequency == 0 ) || ( 12 % frequency != 0 )
172
|| settlement.daysTo( maturity ) <= 0)
178
// Function: COUPNUM - taken from GNUMERIC
179
bool kspreadfunc_coupnum( KSContext & context )
187
if ( !getCoupParameter( context, "COUPNUM", settlement, maturity,
188
frequency, basis, eom ) )
192
QDate cDate( maturity );
194
int months = maturity.month() - settlement.month()
195
+ 12 * ( maturity.year() - settlement.year() );
197
subMonths( cDate, months );
199
if ( eom && maturity.daysInMonth() == maturity.day() )
201
while( cDate.daysInMonth() != cDate.day() )
205
if ( settlement.day() >= cDate.day() )
208
result = ( 1 + months / ( 12 / frequency ) );
210
context.setValue( new KSValue( result ) );
215
bool kspreadfunc_accrint( KSContext& context )
217
QValueList<KSValue::Ptr> & args = context.value()->listValue();
221
if ( !KSUtil::checkArgumentsCount( context, 7, "ACCRINT", true ) )
223
if ( !KSUtil::checkArgumentsCount( context, 6, "ACCRINT", true ) )
228
if ( !KSUtil::checkType( context, args[6], KSValue::IntType, true ) )
231
basis = args[6]->intValue();
240
if ( !getDate( context, args[0], maturity ) )
243
if ( !getDate( context, args[1], firstInterest ) )
246
if ( !getDate( context, args[2], settlement ) )
249
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
252
if ( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
255
if ( !KSUtil::checkType( context, args[5], KSValue::DoubleType, true ) )
258
rate = args[3]->doubleValue();
259
par = args[4]->doubleValue();
260
frequency = (int) args[5]->doubleValue();
262
if ( basis < 0 || basis > 4 || ( frequency == 0 ) || ( 12 % (int) frequency != 0 ) )
265
if ( ( settlement.daysTo( firstInterest ) < 0 )
266
|| ( firstInterest.daysTo( maturity ) > 0 ) )
269
double d = daysBetweenDates( maturity, settlement, basis );
270
double y = daysPerYear( maturity, basis );
272
if ( d < 0 || y <= 0 || par <= 0 || rate <= 0 )
275
double coeff = par * rate / frequency;
278
context.setValue( new KSValue( coeff * frequency * n ) );
282
// Function: ACCRINTM
283
bool kspreadfunc_accrintm( KSContext& context )
285
QValueList<KSValue::Ptr> & args = context.value()->listValue();
290
if ( !KSUtil::checkArgumentsCount( context, 5, "ACCRINTM", true ) )
292
if ( !KSUtil::checkArgumentsCount( context, 4, "ACCRINTM", true ) )
294
if ( !KSUtil::checkArgumentsCount( context, 3, "ACCRINTM", true ) )
299
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
302
par = args[3]->doubleValue();
307
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
309
if ( !KSUtil::checkType( context, args[4], KSValue::IntType, true ) )
312
par = args[3]->doubleValue();
313
basis = args[4]->intValue();
320
if ( !getDate( context, args[0], issue ) )
323
if ( !getDate( context, args[1], maturity ) )
326
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
329
rate = args[2]->doubleValue();
331
double d = daysBetweenDates( issue, maturity, basis );
332
double y = daysPerYear( issue, basis );
334
if ( d < 0 || y <= 0 || par <= 0 || rate <= 0 || basis < 0 || basis > 4 )
337
context.setValue( new KSValue( par * rate * d / y ) );
342
bool kspreadfunc_disc( KSContext& context )
344
QValueList<KSValue::Ptr> & args = context.value()->listValue();
348
if ( !KSUtil::checkArgumentsCount( context, 5, "DISC", true ) )
350
if ( !KSUtil::checkArgumentsCount( context, 4, "DISC", true ) )
355
if ( !KSUtil::checkType( context, args[4], KSValue::IntType, true ) )
358
basis = args[4]->intValue();
364
if ( !getDate( context, args[0], settlement ) )
367
if ( !getDate( context, args[1], maturity ) )
370
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
373
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
376
double par = args[2]->doubleValue();
377
double redemp = args[3]->doubleValue();
379
double y = daysPerYear( settlement, basis );
380
double d = daysBetweenDates( settlement, maturity, basis );
382
if ( y <= 0 || d <= 0 || basis < 0 || basis > 4 || redemp == 0 )
385
context.setValue( new KSValue( ( redemp - par ) / redemp * ( y / d ) ) );
390
// Function: TBILLPRICE
391
bool kspreadfunc_tbillprice( KSContext& context )
393
QValueList<KSValue::Ptr> & args = context.value()->listValue();
395
if ( !KSUtil::checkArgumentsCount( context, 3, "TBILLPRICE", true ) )
402
if ( !getDate( context, args[0], settlement ) )
405
if ( !getDate( context, args[1], maturity ) )
408
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
411
discount = args[2]->doubleValue();
413
double days = settlement.daysTo( maturity );
415
if ( settlement > maturity || discount < 0 || days > 265 )
418
context.setValue( new KSValue( 100 * ( 1.0 - ( discount * days ) / 360.0 ) ) );
422
// Function: TBILLYIELD
423
bool kspreadfunc_tbillyield( KSContext& context )
425
QValueList<KSValue::Ptr> & args = context.value()->listValue();
427
if ( !KSUtil::checkArgumentsCount( context, 3, "TBILLYIELD", true ) )
434
if ( !getDate( context, args[0], settlement ) )
437
if ( !getDate( context, args[1], maturity ) )
440
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
443
rate = args[2]->doubleValue();
445
double days = settlement.daysTo( maturity );
447
if ( settlement > maturity || rate <= 0 || days > 265 )
450
context.setValue( new KSValue( ( 100.0 - rate ) / rate * ( 360.0 / days ) ) );
455
bool kspreadfunc_tbilleq( KSContext& context )
457
QValueList<KSValue::Ptr> & args = context.value()->listValue();
459
if ( !KSUtil::checkArgumentsCount( context, 3, "TBILLEQ", true ) )
466
if ( !getDate( context, args[0], settlement ) )
469
if ( !getDate( context, args[1], maturity ) )
472
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
475
discount = args[2]->doubleValue();
477
double days = settlement.daysTo( maturity );
479
if ( settlement > maturity || discount < 0 || days > 265 )
482
double divisor = 360.0 - discount * days;
487
context.setValue( new KSValue( 365.0 * discount / divisor ) );
491
// Function: RECEIVED
492
bool kspreadfunc_received( KSContext& context )
494
QValueList<KSValue::Ptr> & args = context.value()->listValue();
498
if ( !KSUtil::checkArgumentsCount( context, 5, "RECEIVED", true ) )
500
if ( !KSUtil::checkArgumentsCount( context, 4, "RECEIVED", true ) )
505
if ( !KSUtil::checkType( context, args[4], KSValue::IntType, true ) )
508
basis = args[4]->intValue();
514
if ( !getDate( context, args[0], settlement ) )
517
if ( !getDate( context, args[1], maturity ) )
520
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
523
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
526
double investment = args[2]->doubleValue();
527
double discount = args[3]->doubleValue();
529
double d = daysBetweenDates( settlement, maturity, basis );
530
double y = daysPerYear( settlement, basis );
532
if ( d <= 0 || y <= 0 || basis < 0 || basis > 4 )
535
double x = 1.0 - ( discount * d / y );
540
context.setValue( new KSValue( investment / x ) );
544
// Function: DOLLARDE
545
bool kspreadfunc_dollarde( KSContext& context )
547
QValueList<KSValue::Ptr> & args = context.value()->listValue();
549
if ( !KSUtil::checkArgumentsCount( context, 2, "DOLLARDE", true ) )
552
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
555
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
558
double d = args[0]->doubleValue();
559
int f = (int) args[1]->intValue();
572
double fl = floor( d );
575
context.setValue( new KSValue( fl + ( r * pow( 10.0, n ) / (double) f ) ) );
579
// Function: DOLLARFR
580
bool kspreadfunc_dollarfr( KSContext& context )
582
QValueList<KSValue::Ptr> & args = context.value()->listValue();
584
if ( !KSUtil::checkArgumentsCount( context, 2, "DOLLARFR", true ) )
587
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
590
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
593
double d = args[0]->doubleValue();
594
int f = (int) args[1]->intValue();
607
double fl = floor( d );
610
context.setValue( new KSValue( fl + ( ( r * (double) f ) / pow( 10.0, n ) ) ) );
615
bool kspreadfunc_intrate( KSContext& context )
617
QValueList<KSValue::Ptr> & args = context.value()->listValue();
621
if ( !KSUtil::checkArgumentsCount( context, 5, "INTRATE", true ) )
623
if ( !KSUtil::checkArgumentsCount( context, 4, "INTRATE", true ) )
628
if ( !KSUtil::checkType( context, args[4], KSValue::IntType, true ) )
631
basis = args[4]->intValue();
639
if ( !getDate( context, args[0], settlement ) )
642
if ( !getDate( context, args[1], maturity ) )
645
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
648
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
651
investment = args[2]->doubleValue();
652
redemption = args[3]->doubleValue();
654
double d = daysBetweenDates( settlement, maturity, basis );
655
double y = daysPerYear( settlement, basis );
657
if ( d <= 0 || y <= 0 || investment == 0 || basis < 0 || basis > 4 )
660
double result = ( redemption -investment ) / investment * ( y / d );
662
context.setValue( new KSValue( result ) );
667
// Function: DURATION
668
bool kspreadfunc_duration( KSContext& context )
670
QValueList<KSValue::Ptr> & args = context.value()->listValue();
672
if ( !KSUtil::checkArgumentsCount( context, 3, "DURATION", true ) )
675
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
677
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
679
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
682
double rate = args[0]->doubleValue();
683
double pv = args[1]->doubleValue();
684
double fv = args[2]->doubleValue();
688
if ( fv == 0.0 || pv == 0.0 )
693
context.setValue( new KSValue( log( fv / pv ) / log( 1.0 + rate ) ) );
698
bool kspreadfunc_pmt( KSContext& context )
700
QValueList<KSValue::Ptr> & args = context.value()->listValue();
705
if ( !KSUtil::checkArgumentsCount( context, 5, "PMT", false ) )
709
if ( !KSUtil::checkArgumentsCount( context, 4, "PMT", false ) )
713
if ( !KSUtil::checkArgumentsCount( context, 3, "PMT", true ) )
718
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
720
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
722
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
726
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
728
fv = args[3]->doubleValue();
732
if ( !KSUtil::checkType( context, args[4], KSValue::IntType, true ) )
734
type = args[4]->intValue();
737
double rate = args[0]->doubleValue();
738
double nper = args[1]->doubleValue();
739
double pv = args[2]->doubleValue();
741
context.setValue( new KSValue( getPay( rate, nper, pv, fv, type ) ) );
746
bool kspreadfunc_nper( KSContext& context )
748
QValueList<KSValue::Ptr> & args = context.value()->listValue();
753
if ( KSUtil::checkArgumentsCount( context, 5, "NPER", true ) )
755
if ( !KSUtil::checkType( context, args[4], KSValue::IntType, true ) )
757
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
760
fv = args[3]->doubleValue();
761
type = args[4]->intValue();
764
if ( KSUtil::checkArgumentsCount( context, 4, "NPER", true ) )
767
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
770
fv = args[3]->doubleValue();
773
if ( !KSUtil::checkArgumentsCount( context, 3, "NPER", false ) )
776
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
778
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
780
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
783
double rate = args[0]->doubleValue();
784
double pmt = args[1]->doubleValue();
785
double pv = args[2]->doubleValue();
790
// taken from Gnumeric
791
double d = ( pmt * ( 1.0 + rate * type ) - fv * rate );
792
double d2 = pv * rate + pmt * ( 1.0 + rate * type );
799
context.setValue( new KSValue( log( res ) / log( 1.0 + rate ) ) );
804
bool kspreadfunc_ispmt( KSContext& context )
806
QValueList<KSValue::Ptr> & args = context.value()->listValue();
808
if ( !KSUtil::checkArgumentsCount( context, 4, "ISPMT", false ) )
811
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
813
if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
815
if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
817
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
820
double rate = args[0]->doubleValue();
821
int per = args[1]->intValue();
822
int nper = args[2]->intValue();
823
double pv = args[3]->doubleValue();
825
if ( per < 1 || per > nper )
828
double d = -pv * rate;
830
context.setValue( new KSValue( d - ( d / nper * per ) ) );
835
bool kspreadfunc_ipmt( KSContext& context )
837
QValueList<KSValue::Ptr>& args = context.value()->listValue();
846
if ( KSUtil::checkArgumentsCount( context, 6, "IPMT", true ) )
848
if ( !KSUtil::checkType( context, args[5], KSValue::IntType, true ) )
850
if ( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
852
type = args[5]->intValue();
853
fv = args[4]->doubleValue();
856
if ( KSUtil::checkArgumentsCount( context, 5, "IPMT", true ) )
858
if ( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
861
fv = args[4]->doubleValue();
864
if ( !KSUtil::checkArgumentsCount( context, 4, "IPMT", false ) )
868
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
870
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
872
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
874
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
877
rate = args[0]->doubleValue();
878
per = args[1]->doubleValue();
879
nper = args[2]->doubleValue();
880
pv = args[3]->doubleValue();
882
double payment = getPay( rate, nper, pv, fv, type );
883
double ipmt = -getPrinc( pv, payment, rate, per - 1 );
885
context.setValue( new KSValue( ipmt * rate ) );
890
/* Returns future value, given current value, interest rate and time */
891
bool kspreadfunc_fv( KSContext& context )
893
QValueList<KSValue::Ptr>& args = context.value()->listValue();
895
if ( !KSUtil::checkArgumentsCount( context, 3, "FV", true ) )
898
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
900
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
902
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
905
double present = args[0]->doubleValue();
906
double interest = args[1]->doubleValue();
907
double periods = args[2]->doubleValue();
909
context.setValue( new KSValue( present * pow(1+interest, periods)));
913
// Function: compound
914
/* Returns value after compounded interest, given principal, rate, periods
916
bool kspreadfunc_compound( KSContext& context )
918
QValueList<KSValue::Ptr>& args = context.value()->listValue();
920
if ( !KSUtil::checkArgumentsCount( context, 4, "compound", true ) )
923
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
925
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
927
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
929
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
931
double principal = args[0]->doubleValue();
932
double interest = args[1]->doubleValue();
933
double periods = args[2]->doubleValue();
934
double years = args[3]->doubleValue();
936
context.setValue( new KSValue( principal * pow(1+(interest/periods),
942
// Function: continuous
943
/* Returns value after continuous compounding of interest, given prinicpal,
945
bool kspreadfunc_continuous( KSContext& context )
947
// If you still don't understand this, let me know! ;-) jsinger@leeta.net
948
QValueList<KSValue::Ptr>& args = context.value()->listValue();
950
if ( !KSUtil::checkArgumentsCount( context, 3, "continuous", true ) )
953
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
955
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
957
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
959
double principal = args[0]->doubleValue();
960
double interest = args[1]->doubleValue();
961
double years = args[2]->doubleValue();
964
context.setValue( new KSValue( principal * exp(interest * years)));
969
bool kspreadfunc_pv( KSContext& context )
971
/* Returns presnt value, given future value, interest rate and years */
972
QValueList<KSValue::Ptr>& args = context.value()->listValue();
974
if ( !KSUtil::checkArgumentsCount( context, 3, "PV", true ) )
977
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
979
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
981
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
983
double future = args[0]->doubleValue();
984
double interest = args[1]->doubleValue();
985
double periods = args[2]->doubleValue();
988
context.setValue( new KSValue( future / pow(1+interest, periods)));
992
// Function: PV_annuity
993
bool kspreadfunc_pv_annuity( KSContext& context )
995
/* Returns present value of an annuity or cash flow, given payment,
997
periods, initial amount and whether payments are made at the start (TRUE)
998
or end of a period */
1000
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1002
if ( !KSUtil::checkArgumentsCount( context, 3, "PV_annuity", true ) )
1005
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1007
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1009
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1011
double amount = args[0]->doubleValue();
1012
double interest = args[1]->doubleValue();
1013
double periods = args[2]->doubleValue();
1016
result = amount * (1 - 1/(pow( (1+interest), periods ))) / interest ;
1018
context.setValue( new KSValue( result ) );
1023
// Function: FV_annnuity
1024
bool kspreadfunc_fv_annuity( KSContext& context )
1026
/* Returns future value of an annuity or cash flow, given payment, interest
1029
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1031
if ( !KSUtil::checkArgumentsCount( context, 3, "FV_annuity", true ) )
1034
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1036
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1038
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1040
double amount= args[0]->doubleValue();
1041
double interest = args[1]->doubleValue();
1042
double periods = args[2]->doubleValue();
1046
result = amount * ((pow( (1+interest),periods))/interest - 1/interest) ;
1048
context.setValue( new KSValue( result ) );
1053
// Function: effective
1054
bool kspreadfunc_effective( KSContext& context )
1056
/* Returns effective interest rate given nominal rate and periods per year */
1058
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1060
if ( !KSUtil::checkArgumentsCount( context, 2, "effective", true ) )
1063
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1065
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1067
double nominal = args[0]->doubleValue();
1068
double periods = args[1]->doubleValue();
1070
context.setValue( new KSValue( pow( 1 + (nominal/periods), periods )- 1 ) );
1075
// Function: zero_coupon
1076
bool kspreadfunc_zero_coupon( KSContext& context )
1078
/* Returns effective interest rate given nominal rate and periods per year */
1080
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1082
if ( !KSUtil::checkArgumentsCount( context, 3, "zero_coupon", true ) )
1085
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1087
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1089
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1091
double face = args[0]->doubleValue();
1092
double rate = args[1]->doubleValue();
1093
double years = args[2]->doubleValue();
1095
context.setValue( new KSValue( face / pow( (1 + rate), years ) ) );
1100
// Function: level_coupon
1101
bool kspreadfunc_level_coupon( KSContext& context )
1103
/* Returns effective interest rate given nominal rate and periods per year */
1105
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1107
if ( !KSUtil::checkArgumentsCount( context, 5, "level_coupon", true ) )
1110
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1112
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1114
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1116
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
1118
if ( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
1120
double face = args[0]->doubleValue();
1121
double coupon_rate = args[1]->doubleValue();
1122
double coupon_year = args[2]->doubleValue();
1123
double years = args[3]->doubleValue();
1124
double market_rate = args[4]->doubleValue();
1126
double coupon = coupon_rate * face / coupon_year;
1127
double interest = market_rate/coupon_year;
1128
double pv_annuity = (1 - 1/(pow( (1+interest), (years*coupon_year) ))) / interest ;
1129
context.setValue( new KSValue( coupon * pv_annuity + (face/ pow( (1+interest), (years*coupon_year) ) ) ) );
1134
// Function: nominal
1135
bool kspreadfunc_nominal( KSContext& context )
1137
/* Returns nominal interest rate given effective rate and periods per year */
1139
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1141
if ( !KSUtil::checkArgumentsCount( context, 2, "nominal", true ) )
1144
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1146
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1148
double effective = args[0]->doubleValue();
1149
double periods = args[1]->doubleValue();
1151
if ( periods == 0.0 ) // Check null
1154
context.setValue( new KSValue( periods * (pow( (effective + 1), (1 / periods) ) -1) ) );
1160
/* straight-line depreciation for a single period */
1161
bool kspreadfunc_sln( KSContext& context )
1163
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1165
if ( !KSUtil::checkArgumentsCount( context, 3, "SLN", true ) )
1168
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1170
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1172
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1175
double cost = args[0]->doubleValue();
1176
double salvage_value = args[1]->doubleValue();
1177
double life = args[2]->doubleValue();
1180
if( life <= 0.0 ) return false;
1182
context.setValue( new KSValue( (cost - salvage_value) / life ) );
1188
/* sum-of-years digits depreciation */
1189
bool kspreadfunc_syd( KSContext& context )
1191
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1193
if ( !KSUtil::checkArgumentsCount( context, 4, "SYD", true ) )
1196
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1198
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1200
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1202
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
1205
double cost = args[0]->doubleValue();
1206
double salvage_value = args[1]->doubleValue();
1207
double life = args[2]->doubleValue();
1208
double period = args[3]->doubleValue();
1211
if( life <= 0.0 ) return false;
1213
context.setValue( new KSValue( ( ( (cost - salvage_value) * (life - period + 1) * 2) /
1214
(life * (life + 1.0) ) ) ) ) ;
1220
/* fixed-declining depreciation */
1221
bool kspreadfunc_db( KSContext& context )
1223
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1227
if( KSUtil::checkArgumentsCount( context, 5, "DB", false ) )
1229
if( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
1231
month = args[4]->doubleValue();
1235
if ( !KSUtil::checkArgumentsCount( context, 4, "DB", true ) )
1239
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1241
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1243
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1245
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
1248
double cost = args[0]->doubleValue();
1249
double salvage = args[1]->doubleValue();
1250
double life = args[2]->doubleValue();
1251
double period = args[3]->doubleValue();
1254
if( cost == 0 || life <= 0.0 ) return false;
1255
if( salvage / cost < 0 ) return false;
1257
double rate = 1000 * (1 - pow( (salvage/cost), (1/life) ));
1258
rate = floor( rate + 0.5 ) / 1000;
1260
double total = cost * rate * month / 12;
1264
context.setValue( new KSValue( total ) );
1268
for( int i = 1; i < life; ++i )
1271
context.setValue( new KSValue( rate * (cost-total) ) );
1274
else total += rate * (cost-total);
1276
context.setValue( new KSValue( (cost-total) * rate * (12-month)/12 ) );
1282
/* depreciation per period */
1283
bool kspreadfunc_ddb( KSContext& context )
1285
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1289
if( KSUtil::checkArgumentsCount( context, 5, "DB", false ) )
1291
if( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
1294
factor = args[4]->doubleValue();
1298
if ( !KSUtil::checkArgumentsCount( context, 4, "DB", true ) )
1302
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1304
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1306
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1308
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
1311
double cost = args[0]->doubleValue();
1312
double salvage = args[1]->doubleValue();
1313
double life = args[2]->doubleValue();
1314
double period = args[3]->doubleValue();
1317
if ( cost < 0.0 || salvage < 0.0 || life <= 0.0 || period < 0.0 || factor < 0.0 )
1320
for( int i = 0; i < life; ++i )
1322
double periodDep = ( cost - total ) * ( factor / life );
1323
if ( i == period - 1 )
1325
context.setValue( new KSValue( periodDep ) );
1334
context.setValue( new KSValue( cost - total - salvage ) );
1339
bool kspreadfunc_ppmt( KSContext & context )
1341
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1343
Docs partly copied from OO.
1345
PPMT(Rate;Period;NPER;PV;FV;Type)
1347
Rate is the periodic interest rate.
1348
Period is the amortizement period. P=1 for the first and P=NPER for the last period.
1349
NPER is the total number of periods during which annuity is paid.
1350
PV is the present value in the sequence of payments.
1351
FV (optional) is the desired (future) value.
1352
Type (optional) defines the due date. F=1 for payment at the beginning of a period and F=0 for payment at the end of a period.
1358
if ( !KSUtil::checkArgumentsCount( context, 6, "PPMT", false ) )
1362
if ( !KSUtil::checkArgumentsCount( context, 5, "PPMT", false ) )
1366
if ( !KSUtil::checkArgumentsCount( context, 4, "PPMT", true ) )
1371
if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
1373
if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
1375
if ( !KSUtil::checkType( context, args[2], KSValue::DoubleType, true ) )
1377
if ( !KSUtil::checkType( context, args[3], KSValue::DoubleType, true ) )
1381
if ( !KSUtil::checkType( context, args[4], KSValue::DoubleType, true ) )
1383
fv = args[4]->doubleValue();
1387
if ( !KSUtil::checkType( context, args[5], KSValue::IntType, true ) )
1389
type = args[5]->intValue();
1392
double rate = args[0]->doubleValue();
1393
double period = args[1]->doubleValue();
1394
double nper = args[2]->doubleValue();
1395
double pv = args[3]->doubleValue();
1397
double pay = getPay( rate, nper, pv, fv, type );
1398
double ipmt = -getPrinc( pv, pay, rate, period - 1 ) * rate;
1400
context.setValue( new KSValue( pay - ipmt ) );
1406
bool kspreadfunc_euro( KSContext& context )
1408
QValueList<KSValue::Ptr>& args = context.value()->listValue();
1410
if ( !KSUtil::checkArgumentsCount( context, 1, "EURO", true ) )
1413
if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
1416
QString currency = args[0]->stringValue().upper();
1419
if( currency == "ATS" ) result = 13.7603; // Austria
1420
else if( currency == "BEF" ) result = 40.3399; // Belgium
1421
else if( currency == "DEM" ) result = 1.95583; // Germany
1422
else if( currency == "ESP" ) result = 166.386; // Spain
1423
else if( currency == "FIM" ) result = 5.94573; // Finland
1424
else if( currency == "FRF" ) result = 6.55957; // France
1425
else if( currency == "GRD" ) result = 340.75; // Greece
1426
else if( currency == "IEP" ) result = 0.787564; // Ireland
1427
else if( currency == "ITL" ) result = 1936.27; // Italy
1428
else if( currency == "LUX" ) result = 40.3399; // Luxemburg
1429
else if( currency == "NLG" ) result = 2.20371; // Nederland
1430
else if( currency == "PTE" ) result = 200.482; // Portugal
1432
if( result <= 0 ) return false;
1434
context.setValue( new KSValue( result ) );