mirror of
https://github.com/zeroflag/fcl.git
synced 2025-01-11 20:01:10 +01:00
fixed finance/discounting, added finance/NPV, finance/IRR
This commit is contained in:
parent
7fa71a71a9
commit
390fce921c
5 changed files with 45 additions and 3 deletions
|
@ -85,6 +85,7 @@
|
||||||
: remove ( l o -- l ) swap :remove/O jvm-call-method ;
|
: remove ( l o -- l ) swap :remove/O jvm-call-method ;
|
||||||
: keys ( d -- l ) :keys jvm-call-method ;
|
: keys ( d -- l ) :keys jvm-call-method ;
|
||||||
: values ( d -- l ) :values jvm-call-method ;
|
: values ( d -- l ) :values jvm-call-method ;
|
||||||
|
: sum ( c -- n ) 0 swap { + } each ;
|
||||||
|
|
||||||
: ... ( lower upper step -- lst ) :com.vectron.fcl.types.Range/create/NNN jvm-call-static ;
|
: ... ( lower upper step -- lst ) :com.vectron.fcl.types.Range/create/NNN jvm-call-static ;
|
||||||
: .. ( lower upper -- lst ) 1 ... ;
|
: .. ( lower upper -- lst ) 1 ... ;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
: else immediate ['] jmp , (dummy) swap resolve ;
|
: else immediate ['] jmp , (dummy) swap resolve ;
|
||||||
: then immediate resolve ;
|
: then immediate resolve ;
|
||||||
: begin immediate here ;
|
: begin immediate here ;
|
||||||
|
: again immediate ['] jmp , (offset) ;
|
||||||
: while immediate ['] jmp#f , (dummy) ;
|
: while immediate ['] jmp#f , (dummy) ;
|
||||||
: repeat immediate swap ['] jmp , (offset) resolve ;
|
: repeat immediate swap ['] jmp , (offset) resolve ;
|
||||||
: until immediate ['] jmp#f , (offset) ;
|
: until immediate ['] jmp#f , (offset) ;
|
||||||
|
|
|
@ -18,3 +18,33 @@
|
||||||
: torch ( n -- ) :com.vectron.forthcalc.support.Torch/toggle/O jvm-call-static ;
|
: torch ( n -- ) :com.vectron.forthcalc.support.Torch/toggle/O jvm-call-static ;
|
||||||
|
|
||||||
: match: immediate ` lastword set-predicate ;
|
: match: immediate ` lastword set-predicate ;
|
||||||
|
|
||||||
|
: npv ( cashflow rate -- n )
|
||||||
|
-> rate 0 => year
|
||||||
|
{ rate year @ dis year inc } map sum ;
|
||||||
|
|
||||||
|
: npv* ( .. rate -- n ) >r list* r> npv ;
|
||||||
|
|
||||||
|
: npv/npv' ( cashflow rate -- npv/npv' )
|
||||||
|
1+ -> rate 0 => n
|
||||||
|
0 0 rot {
|
||||||
|
dup ( each ) n @ neg * rate n @ 1+ neg pow * ( npv' ) rot +
|
||||||
|
swap ( each ) rate n @ pow / ( npv ) rot +
|
||||||
|
swap
|
||||||
|
n inc
|
||||||
|
} each / ;
|
||||||
|
|
||||||
|
var: irr-guess 0 irr-guess !
|
||||||
|
|
||||||
|
: irr ( cashflow -- n/nil )
|
||||||
|
-> cashflow irr-guess @ 100 / => guess
|
||||||
|
1000 0 do
|
||||||
|
guess @ cashflow guess @ npv/npv' - ( new guess )
|
||||||
|
dup guess @ - abs 0.01 < if
|
||||||
|
100 * unloop exit
|
||||||
|
then
|
||||||
|
guess !
|
||||||
|
loop
|
||||||
|
nil ;
|
||||||
|
|
||||||
|
: irr* ( cashflow -- n ) list* irr ;
|
|
@ -18,7 +18,7 @@
|
||||||
( years ) 1 -
|
( years ) 1 -
|
||||||
repeat
|
repeat
|
||||||
drop ( years ) r> r> 2drop ;
|
drop ( years ) r> r> 2drop ;
|
||||||
: dis ( b i n -- t ) swap 100 / neg 1+ swap pow * ;
|
: dis ( b i n -- t ) swap 100 / 1+ swap pow / ;
|
||||||
: tip1 ( n -- n ) 15 percent ;
|
: tip1 ( n -- n ) 15 percent ;
|
||||||
: tip2 ( bill split -- total tip ) / dup 115 percent swap 15 percent ;
|
: tip2 ( bill split -- total tip ) / dup 115 percent swap 15 percent ;
|
||||||
( trigonometry )
|
( trigonometry )
|
||||||
|
|
|
@ -67,6 +67,7 @@ public class FclTest {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
|
System.out.println("Transcript: " + transcript.content());
|
||||||
assertEquals(0, fcl.stackSize());
|
assertEquals(0, fcl.stackSize());
|
||||||
assertEquals(0, fcl.rStackSize());
|
assertEquals(0, fcl.rStackSize());
|
||||||
assertEquals(0, evalPop("psp @").longValue());
|
assertEquals(0, evalPop("psp @").longValue());
|
||||||
|
@ -210,12 +211,19 @@ public class FclTest {
|
||||||
@Test
|
@Test
|
||||||
public void testFinance() {
|
public void testFinance() {
|
||||||
assertEquals(1216.65, evalPop("1000 4 5 cin1").doubleValue(), 0.01);
|
assertEquals(1216.65, evalPop("1000 4 5 cin1").doubleValue(), 0.01);
|
||||||
assertEquals(815.37, evalPop("1000 4 5 dis").doubleValue(), 0.01);
|
assertEquals(821.93, evalPop("1000 4 5 dis").doubleValue(), 0.01);
|
||||||
|
assertEquals(558.39, evalPop("1000 6 10 dis").doubleValue(), 0.01);
|
||||||
evalDoubles("1000.0 4 5 100 cin2", asList(1000.0, 2240.0, 3529.6, 4870.784, 6265.61536, 7716.2399744));
|
evalDoubles("1000.0 4 5 100 cin2", asList(1000.0, 2240.0, 3529.6, 4870.784, 6265.61536, 7716.2399744));
|
||||||
assertEquals(15, evalPop("100 tip1").doubleValue(), 0.01);
|
assertEquals(15, evalPop("100 tip1").doubleValue(), 0.01);
|
||||||
evalDoubles("100 1 tip2", asList(115.0, 15.0));
|
evalDoubles("100 1 tip2", asList(115.0, 15.0));
|
||||||
evalDoubles("100 3 tip2", asList(38.33, 5));
|
evalDoubles("100 3 tip2", asList(38.33, 5));
|
||||||
evalDoubles("3421 5 tip2", asList(786.83, 102.63));
|
evalDoubles("3421 5 tip2", asList(786.83, 102.63));
|
||||||
|
assertEquals(-371.68, evalPop("[ -1000 50 100 150 200 250 ] 5 npv").doubleValue(), 0.01);
|
||||||
|
assertEquals(-371.68, evalPop("-1000 50 100 150 200 250 5 npv*").doubleValue(), 0.01);
|
||||||
|
assertEquals(-250, evalPop("[ -1000 50 100 150 200 250 ] 0 npv").doubleValue(), 0.01);
|
||||||
|
assertEquals(12.006, evalPop("[ -500 50 100 150 200 250 ] irr").doubleValue(), 0.01);
|
||||||
|
assertEquals(-7.431, evalPop("[ -1000 50 100 150 200 250 ] irr").doubleValue(), 0.01);
|
||||||
|
assertEquals(-28.482, evalPop("-10 irr-guess ! -5000 200 230 400 202 450 irr*").doubleValue(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evalDoubles(String script, List<Number> expected) {
|
private void evalDoubles(String script, List<Number> expected) {
|
||||||
|
@ -809,6 +817,8 @@ public class FclTest {
|
||||||
assertEquals(true, evalPop("m 2 at").boolValue());
|
assertEquals(true, evalPop("m 2 at").boolValue());
|
||||||
assertEquals(1, evalPop("m 2 index-of").intValue());
|
assertEquals(1, evalPop("m 2 index-of").intValue());
|
||||||
assertEquals(0, evalPop("m clear m size").intValue());
|
assertEquals(0, evalPop("m clear m size").intValue());
|
||||||
|
assertEquals(6, evalPop("[ 4 -1 3 ] sum").intValue());
|
||||||
|
assertEquals(1+2+3+4+5, evalPop("1 5 .. sum").intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue