[erlang-questions] Feedback for my first non-trivial Erlang program
Paul Wolf
paul.wolf23@REDACTED
Tue Dec 15 01:45:26 CET 2015
Hi,
I am totally new to Erlang and functional programming in general and
tried to build a little program, after I read most of the "sequential
programming" part of the Joe Armstrong book. While my program seems to
work, I have still _big_ troubles in two departments:
- my program is crazy slow as it seems to do a lot of redundant
calculations. To me it seems functional and I don't really know how to
solve this kind of (performance) issue
- while I was able to program the logic in a mostly functional style,
I had a hard time writing it and even some minutes after writing it,
it is quite hard to read for me
As I am totally knew to this stuff (while being an experienced Java
developer/software engineer in general), I would highly appreciate
some feedback to the following code:
The programm basically takes some parameters (hardcoded... i know...)
and tells you what your financial possesions are, if you save your
money in stocks which in turn have an expected yield, etc., pp.
The major part (first ~50 lines) seems fine to me and don't cause me
much headache. However as soon as I start considering taxes (which in
my country you pay on realized profits), stuff gets worriesome. Could
you please review and comment the "tax" functions in particular (on a
technical level - not functional)? For calculating the profit you have
to keep track of when you bought how much and you have to sell your
oldest positions first. For simplification I didn't model stocks, but
instead you basically just put money (without consideration of stock
quantities) into the security account and it yields. The tax method
gets called by the way twice, but also gets evaluated twice (why? is
there no cache? is my approach wrong?) and takes up a lot of
performance!
Any feedback is much appreciated! Here is the code without further ado:
-module(pension2).
-export([totalBalance/1]).
%% 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) -> caBalance(T-1) + salary(T-1) - expenses(T-1) - tradingFees(T-1).
%% balance of security account - rises while working - can rise while
not working if yield > expenses
saBalance(0) -> saBalanceStart();
saBalance(T) -> (saBalance(T-1)*yieldRate() + 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) -> 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) -> profit(X,T,portfolio(T))*taxRate().
%% what is in the security account at time T:
portfolio(T) ->
case working(T) of
true -> [{investments(X),X} || X <- lists:seq(0,T)];
false -> remove(investments(T-1),T,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-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 - originalValue(X,T-Time);
false -> X - (Amount + profit((X - 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).
More information about the erlang-questions
mailing list