Created
December 15, 2015 14:18
-
-
Save ferd/ab5fed3b8ffe4b226755 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(pension2). | |
-export([totalBalance/1]). | |
%% memoization uses a process dictionary. While hackish and not portable | |
%% through processes, a PD of this kind has the advantage of being | |
%% garbage collected and being returned in a stack trace. There is also no | |
%% copying (see: comments over the macros) or locking needed. | |
-define(memoize(E), lazy_memoize(fun()-> E end)). | |
lazy_memoize(F) when is_function(F) -> | |
case erlang:get(F) of | |
undefined -> | |
erlang:put(F,F()), | |
erlang:get(F); | |
X -> X | |
end. | |
%% total of what you own: | |
totalBalance(T) -> caBalance(T) + saBalance(T). | |
%% balance of cash account - is constant since all money not spend is invested: | |
caBalance(0) -> caBalanceStart(); | |
caBalance(T) -> | |
?memoize(caBalance(T-1)) + | |
?memoize(salary(T-1)) - | |
?memoize(expenses(T-1)) - | |
?memoize(tradingFees(T-1)). | |
%% balance of security account - rises while working - can rise while not working if yield > expenses | |
saBalance(0) -> saBalanceStart(); | |
saBalance(T) -> ?memoize(saBalance(T-1)) * yieldRate() + ?memoize(investments(T-1)). | |
%% everything spend on securities - in case of not working fees and taxes are directly offset by sells | |
tradingFees(T) -> | |
case working(T) of | |
true -> investments(T) + transactionFee(); | |
false -> investments(T) + tax(expenses(T),T) + transactionFee() | |
end. | |
%% what is actually spend on stocks: | |
investments(T) -> | |
case working(T) of | |
true-> salary(T) - expenses(T) - transactionFee(); | |
false-> -expenses(T) - tax(expenses(T),T) - transactionFee() | |
end. | |
%% salary: | |
salary(0) -> netIncome(); | |
salary(T) -> | |
case working(T) of | |
true -> salary(T-1)*inflationRate(); | |
false -> 0 | |
end. | |
%% expenses | |
expenses(0) -> expensesStart(); | |
expenses(T) -> ?memoize(expenses(T-1))*inflationRate(). | |
%% still working? | |
working(T) -> T<workingTimeUnits(). | |
%% lots of constants - in respect to months | |
transactionFee() -> 10. | |
workingTimeUnits() -> 60. %%months | |
caBalanceStart() -> 10000. | |
saBalanceStart() -> 10000. | |
netIncome() -> 3000. | |
expensesStart() -> 2000. | |
inflationRate() -> 1.0017. | |
yieldRate() -> 1.004. | |
taxRate() -> 0.2638. | |
%% ------------HERE STARTS THE HEAVY LIFTING----------------- | |
%% used to calc taxes payed on profits | |
tax(X,T) -> ?memoize(profit(X,T,?memoize(portfolio(T))))*taxRate(). | |
%% what is in the security account at time T: | |
portfolio(T) -> | |
case working(T) of | |
true -> [{?memoize(investments(X)),X} || X <- lists:seq(0,T)]; | |
false -> remove(?memoize(investments(T-1)),T,?memoize(portfolio(T-1))) | |
end. | |
%% a helper method for removing positions from the portfolio | |
remove(X,T,[{Amount,Time}|Tail]) -> | |
case currentValue(Amount,T-Time) > X of | |
true -> [{Amount-?memoize(originalValue(X,T-Time)),T}|Tail]; | |
false -> remove(X-currentValue(Amount,T-Time),T,Tail) | |
end. | |
%% tells you what is the actual profit for an amount/revenue generated by selling at a time T | |
profit(X,T,[{Amount,Time}|Tail]) -> | |
case currentValue(Amount,T-Time) > X of | |
true -> X - ?memoize(originalValue(X,T-Time)); | |
false -> X - (Amount + ?memoize(profit((X - ?memoize(currentValue(Amount,T-Time))),T,Tail))) | |
end. | |
%% helper functions for calculation the current and original value of a position | |
currentValue(X,TD) -> X * math:pow(yieldRate(),TD). | |
originalValue(X,TD) -> X / math:pow(yieldRate(),TD) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you write "money denomination" code in erlang Language ?