(*Financial Modelling using the Vector method with Solve*)
Remove["Global`*"]
timestart=AbsoluteTime[];
periods=3;
n=periods+1;
Clear[assignElementsFull,Prev];
(*For assignElementsFull refer to [mg110241] Re:Programatically creating delayed assignment (http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00136.html)*)
assignElementsFull[name_String,elemName_String,length_Integer]:=With[{heldName=ToExpression[name,InputForm,Hold]},Clear@@heldName;
With[{heldElementBaseName=ToExpression[elemName<>name,InputForm,Hold]},Block@@Append[Map[List,heldElementBaseName],Unevaluated[Evaluate[First@heldName]:=Evaluate[Table[First[heldElementBaseName][i],{i,length}]]]]]];
Prev[vec_]:=Flatten[{First[vec],Most[vec]}];
(*establish the variable vectors*)
eqns=Hold[
(*** Projection assumptions ***)
salesgrowthrate==Prev[salesgrowthrate],
expensesgrowthrate==Prev[expensesgrowthrate],
newloan==Prev[newloan],
newcapital==Prev[newcapital],
newassets==Prev[depreciation],
depreciationrate==Prev[depreciationrate],
loanintrate==Prev[loanintrate],
netcashintrate==Prev[netcashintrate],
taxrate==Prev[taxrate],
daysdebtors==Prev[daysdebtors],
daysstock==Prev[daysstock],
dayscreditors==Prev[dayscreditors],
divpayoutratio==Prev[divpayoutratio],
interimdivpropn==Prev[interimdivpropn],
interimprofitpropn==Prev[interimprofitpropn],
interimnewcapitalpropn==Prev[interimnewcapitalpropn],
interimnewloanpropn==Prev[interimnewloanpropn],
interimnewassetspropn==Prev[interimnewassetspropn],
(*** MAIN MODEL ***)
(** P&L **)
sales==Prev[sales](1+salesgrowthrate),
expenses==Prev[expenses](1+expensesgrowthrate),
(* start of interest calculation *)
(*first half*)
intloan1==(Prev[loan]/2+newloan interimnewloanpropn/4)loanintrate,
intcf1==(collections-payments)interimprofitpropn+newcapital interimnewcapitalpropn+newloan interimnewloanpropn- newassets interimnewassetspropn,
(*earnings before interest on cash and after interest on loans*)
deprec1==(Prev[netfixedassets]/2+newassets interimnewassetspropn/4)depreciationrate,
ebcit1==(sales-expenses)interimprofitpropn-deprec1-intloan1 ,
(* The folowing equations solve the circular loop 
cash1[t]==cash[t-1]+intcf1[t]+intcash1[t]-taxpmt1[t],
or, cash1[t]==cash[t-1]+intcf1[t]-intloan1[t]+intcash1[t]-(ebcit1[t]+intcash1[t])*taxrate[t]-provdiv[t-1] (1),
and intcash1[t]==(cash[t-1]+cash1[t])*cashintrate[t]/4 (2),
(1)in(2), intcash1[t]==(cash[t-1]+cash[t-1]+intcf1[t]-intloan1[t]+intcash1[t]-(ebcit1[t]+intcash1[t])*taxrate[t]-provdiv[t-1])*cashintrate[t]/4,
(4 intcash1[t])/cashintrate[t]==cash[t-1]+cash[t-1]+intcf1[t]-intloan1[t]+intcash1[t]-(ebcit1[t]+intcash1[t])*taxrate[t]-provdiv[t-1],
intcash1[t]((4/cashintrate[t])-1+taxrate[t])== 2 cash[t-1]+intcf1[t]-intloan1[t]-ebcit1[t]*taxrate[t]-provdiv[t-1],
intcash1[t]==(2 cash[t-1]+intcf1[t]-intloan1[t]-ebcit1[t]*taxrate[t]-provdiv[t-1])/((4/cashintrate[t])-1+taxrate[t]),*)
intcash1==(2 Prev[netcash]+intcf1-intloan1-ebcit1*taxrate-Prev[provdiv])/((4/netcashintrate)-1+taxrate),
taxpmt1==(ebcit1+intcash1)taxrate,
netcash1==Prev[netcash]+intcf1+intcash1-taxpmt1,
(*second half*)
intloan2==(Prev[loan]/2+newloan interimnewloanpropn/2+newloan(1-interimnewloanpropn)/4)loanintrate,
intcf2==(collections-payments)(1-interimprofitpropn)+newcapital(1-interimnewcapitalpropn)+newloan(1-interimnewloanpropn)-newassets(1-interimnewassetspropn),
deprec2==(Prev[netfixedassets]/2+newassets interimnewassetspropn/2+newassets(1-interimnewassetspropn)/4)depreciationrate,
ebcit2==(sales-expenses)(1-interimprofitpropn)-deprec2-intloan2 ,
(* Solve: cash2[t]==cash1[t]+intcf2[t]-intloan2[t]+intcash2[t]-taxpmt2[t]-div2[t],
or,     cash2[t]==cash1[t]+intcf2[t]-intloan2[t]+intcash2[t]-(ebcit2[t]+intcash2[t])*taxrate[t]-(ebcit1[t]+intcash1[t]+ebcit2[t]+intcash2[t])*(1-taxrate[t])*divpayoutrate[t]*interimdivpropn[t] (1),
and    intcash2[t]==(cash1[t]+cash2[t])*cashintrate[t]/4 (2),
(1)in(2), intcash2[t]==(cash1[t]+cash1[t]+intcf2[t]-intloan2[t]+intcash2[t]-(ebcit2[t]+intcash2[t])*taxrate[t]-(ebcit1[t]+intcash1[t]+ebcit2[t]+intcash2[t])*(1-taxrate[t])*divpayoutratio[t]*interimdivpropn[t])*taxrate[t])*cashintrate[t]/4,
(4 intcash2[t])/cashintrate[t]==cash1[t]+cash1[t]+intcf2[t]-intloan2[t]+intcash2[t]-(ebcit2[t]+intcash2[t])*taxrate[t]-(ebcit1[t]+intcash1[t]+ebcit2[t]+intcash2[t])*(1-taxrate[t])*divpayoutratio[t]*interimdivpropn[t],
intcash2[t]((4/cashintrate[t])-1+taxrate[t]+(1-taxrate[t])*divpayoutratio[t]*interimdivpropn[t])== 2 cash1[t]+intcf2[t]-intloan2[t]-ebcit2[t]*taxrate[t]-(ebcit1[t]+intcash1[t]+ebcit2[t])*(1-taxrate[t])*divpayoutratio[t]*interimdivpropn[t],
intcash2[t]== (2 cash1[t]+intcf2[t]-intloan2[t]-ebcit2[t]*taxrate[t]-(ebcit1[t]+intcash1[t]+ebcit2[t])*(1-taxrate[t])*divpayoutratio[t]*interimdivpropn[t])/((4/cashintrate[t])-1+taxrate[t]+(1-taxrate[t])*divpayoutratio[t]*interimdivpropn[t])*)
divpropn2==(1-taxrate)divpayoutratio interimdivpropn,
intcash2== (2 netcash1+intcf2-intloan2-ebcit2 taxrate-(ebcit1+intcash1+ebcit2)divpropn2)/((4/netcashintrate)-1+taxrate+divpropn2),
(*end of interest calculation *)
interest==intloan1+intloan2-intcash1-intcash2,
depreciation==deprec1+deprec2,
pbt==sales-expenses-depreciation-interest,
tax==pbt taxrate,
netprofit==pbt-tax,
dividend==netprofit divpayoutratio,
(** Balance Sheet **)
netcash==Prev[netcash]+cashflow,
cash==netcash(1+Sign[netcash])/2,
debtors==sales daysdebtors/365,
stock==sales daysstock/365,
fixedassets==Prev[fixedassets]+newassets,
accumdepreciation==Prev[accumdepreciation]+depreciation,
netfixedassets==fixedassets-accumdepreciation,
totalassets==cash+debtors+stock+netfixedassets,
overdraft==-(netcash-cash),
creditors==sales dayscreditors/365,
provdiv==dividend(1-interimdivpropn),
loan==Prev[loan]+newloan,
totalliabilities==overdraft+creditors+provdiv+loan,
retainedprofit==Prev[retainedprofit]+netprofit-dividend,
capital==Prev[capital]+newcapital,
equity==capital+retainedprofit,
balance==totalassets-totalliabilities-equity,
(** Cash Flow **)
collections==sales-(debtors-Prev[debtors]),
payments==expenses-(creditors-Prev[creditors])+(stock-Prev[stock]),
cashflow==collections-payments+newloan+newcapital-newassets-interest-tax-Prev[provdiv]-(dividend-provdiv)
];
(*** Year0 initial conditions ***)
eqnsinitial=Hold[
sales[[1]]==150,
expenses[[1]]==75 ,
depreciation[[1]]==50,
interest[[1]]==5,
pbt[[1]]==sales[[1]]-expenses[[1]]-depreciation[[1]]-interest[[1]],
taxrate[[1]]==0.3,
tax[[1]]==pbt[[1]]taxrate[[1]],
netprofit[[1]]==pbt[[1]]-tax[[1]],
dividend[[1]]==7,
cash[[1]]==100,
debtors[[1]]==30,
stock[[1]]==30, 
fixedassets[[1]]==500,
accumdepreciation[[1]]==313,
netfixedassets[[1]]==fixedassets[[1]]-accumdepreciation[[1]],
totalassets[[1]]==cash[[1]]+debtors[[1]]+stock[[1]]+netfixedassets[[1]],
overdraft[[1]]==0,
creditors[[1]]==20,
provdiv[[1]]==3.5,
loan[[1]]==23.5,
totalliabilities[[1]]==overdraft[[1]]+creditors[[1]]+provdiv[[1]]+loan[[1]],
capital[[1]]==200,
retainedprofit[[1]]==100,
equity[[1]]==capital[[1]]+retainedprofit[[1]],
balance[[1]]==totalassets[[1]]-totalliabilities[[1]]-equity[[1]],
collections[[1]]==sales[[1]]-(debtors[[1]](*-debtors[-1]*)),
payments[[1]]==expenses[[1]]-(creditors[[1]](*-creditors[[0]]*))+(stock[[1]](*-stock[[0]]*)),
cashflow[[1]]==collections[[1]]-payments[[1]]-interest[[1]]-tax[[1]]-dividend[[1]]+newcapital[[1]]+newloan[[1]]-newassets[[1]],
netcash[[1]]==cash[[1]]-overdraft[[1]],
newassets[[1]]==depreciation[[1]],
newloan[[1]]==0,
newcapital[[1]]==0,
salesgrowthrate[[1]]==0.1,
expensesgrowthrate[[1]]==0.1,
depreciationrate[[1]]==0.1,
netcashintrate[[1]]==loanintrate[[1]]/2,
loanintrate[[1]]==0.1,
interimdivpropn[[1]]==0.4,
interimprofitpropn[[1]]==0.6,
interimnewcapitalpropn[[1]]==0.5,
interimnewloanpropn[[1]]==0.5,
interimnewassetspropn[[1]]==0.5,
daysdebtors[[1]]==debtors [[1]]365/sales[[1]],
daysstock[[1]]==stock [[1]]365/sales[[1]],
dayscreditors[[1]]==creditors [[1]]365/sales[[1]],
divpayoutratio[[1]]==dividend[[1]]/netprofit[[1]]
];
(*prepare the vectors*)
lhs=Map[ToString,Cases[eqns,Equal[a_,b_]->a]];
Scan[assignElementsFull[#,"γ",n]&,lhs]
(*solve the initial conditions*)
initial2=Apply[List,Map[ReleaseHold,eqnsinitial]];
initialr=Flatten[Solve[initial2]];
(*solve the main model*)
(*prepare the main model*)
eqns2=Apply[List,Map[ReleaseHold,eqns]];
lhs2=Flatten[Map[Rest,Cases[eqns2,Equal[a_,b_]->a]]];
rhs2=Flatten[Map[Rest,Cases[eqns2,Equal[a_,b_]->b]]];
solutionr=Solve[{lhs2==(rhs2/.initialr)},lhs2];
resultsr=Flatten[{initialr,solutionr}];
Print["Time: ",(AbsoluteTime[]-timestart)/3600,"; Memory Mb: ",N[MaxMemoryUsed[]/10^6]];
(*present output*)
BlankLine={""};
Grid[Join[
{Table[If[i==-1,"Profit & Loss","Year"<>ToString[i]],{i,-1,periods}]},
Map[Join[{If[#=="BlankLine","",#]},ToExpression[#]]&,{"sales","expenses","depreciation","interest","pbt","tax","netprofit","dividend","BlankLine"}]/.resultsr,
{Table[If[i==-1,"Balance Sheet","Year"<>ToString[i]],{i,-1,periods}]},
Map[Join[{If[#=="BlankLine","",#]},ToExpression[#]]&,{"cash","debtors","stock","fixedassets","accumdepreciation","netfixedassets","totalassets","BlankLine",
"overdraft","creditors","provdiv","loan","totalliabilities","BlankLine","capital","retainedprofit","equity","BlankLine","balance","BlankLine"}]/.resultsr,
{Table[If[i==-1,"CashFlow","Year"<>ToString[i]],{i,-1,periods}]},
Map[Join[{If[#=="BlankLine","",#]},ToExpression[#]]&,{"collections","payments","interest","tax","dividend","newcapital","newloan","newassets","cashflow","cash"
}]/.resultsr], Alignment->{{Left}},Dividers->{{},Flatten[{False,True,Table[False,{9}],True,Table[False,{20}],True}]}]