Sunday, June 12, 2011

Monte Carlo #2 | The Practical Implementation of The Model

Let's continue the topic. Today I am going to show an example of the practical implementation of the model, which was described in the previous post. The calculations are made in Maple. If you are not familiar with this framework I highly recommend you to read the book of J.S. Dagpunar 'Simulation and Monte Carlo'. You can also download samples here.

Mathematicians say that the simulation is rather time consuming in Maple. It's not our case, because simulation in finance is not as compicated as in physics or neurobiology. We're going to generate only 10 000 scenarious for 48 periods, that's not so much. Before going to the algorythm I'd like to answer two nice questions I was asked after the publicaation of the previous post:

> The definition of the conversion among the practicioners is a bit different from one you operate with in your model. What is the conversion rate in your opinion?

Thanks a lot for your comment. I have not noticed that traditionally conversion is understood as the relation of new customers and unique visitors. I prefer to use conversion of unique visitors into customers in order to show the share of all customers from the total number of unique visitors.

> You predict unique visitors and the conversion of them into customers. Why don't you predict customers instead of all that staff?

This question is quiet controversal. If we deal with the model like the one, which was described in the previous post, we can say that the answer is evident. Predicting the future flow of customers is a more rational approach, but there is an idea I want to share with you. According to my research, I've found out that there is correlation between the number of unique visitors and the conversion rate. The linear regression model was not significant. And I decided that it would be more correct to analize the functional dependance between the flow of unique visitors and different contingency factors. The stochastic nature of conversion is my assumption, which was prooved by my observations. I see volatility of conversion as a sort of noise, which does'nt allow us to make more accurate predictions. That's why I see it rational to exclude that noise at the very beginning, before some sophisticated models of prediction are built.

Let's go to the implementation of the model, described in the previous post.

Firstly, we begin to generate scenarious for the flow of future visors. We define the parameters from the equation (3) in the previous post. S[0] is the initial point, r is the growth rate, sigma is the level of volatility, T - the number of periods (in months). M - the number of scenarious. N is the number of 'dots', which makes the graph more detailed, but is not needed thats why we define it the same as T.
restart;
with(Statistics):
Vis[0]:= 5000: rvis:= 0.15: sigmavis:= 0.05: N:= 48: M:= 10000: T:= 48: h := T/N: 
randomize():
U := RandomVariable(Normal(0, 1)):
W := exp((rvis-(1/2)*sigmavis^2)*h+sigmavis*sqrt(h)*U):
Visitors := [seq(Sample(W, N), i = 1 .. M)]:
for i to M do Visitors[i][1] := Vis[0] end do:
Visitors := map(CumulativeProduct, Visitors):
Xrng := [seq(h*i, i = 1 .. N)]:

Then we generate scenarious for the conversion. The parameters are relatively the same, but with different values. There is a very important thing
I want you to notice. The convertion rate is taken as a mean from all its' scenarious in each particular period.
Conv[0]:= 0.07: rconv:= 0.0001: sigmaconv:= 0.05: N:= 48: M:= 1000: T:= 48: h := T/N:
randomize():
U := RandomVariable(Normal(0, 1)):
W := exp((rconv-(1/2)*sigmaconv^2)*h+sigmaconv*sqrt(h)*U):
SPr := [seq(Sample(W, N), i = 1 .. M)]:
for i to M do SPr[i][1] := Conv[0] end do:
SPr := map(CumulativeProduct, SPr):
Xrng := [seq(h*i, i = 1 .. N)]:
SD := 50:
for k to N do
Conv[k]:=Mean([seq(SPr[i][k],i=1..M)])
end do:

After that we try to predict the dynamics of the changing portfolio structure.
Cast[0]:= 0.15: rind:= 0.0045: sigmaind:= 0.000001: N:= 48: M:= 1000: T:= 48: h := T/N:
randomize():
U := RandomVariable(Normal(0, 1)):
W := exp((rind-(1/2)*sigmaind^2)*h+sigmaind*sqrt(h)*U):
SPr := [seq(Sample(W, N), i = 1 .. M)]:
for i to M do SPr[i][1] := Ind[0] end do:
SPr := map(CumulativeProduct, SPr):
Xrng := [seq(h*i, i = 1 .. N)]:
for k to N do
AvPers[k]:=Mean([seq(SPr[i][k],i=1..M)]):
AvSelf[k]:=1-AvPers[k]:
end do:
To predict sales revenue we'll need ARPU (average revenue per user) in each product category:
arpuSelf:=500:
arpuPers:=1500:
Cost of revenue is considered to be 85% of an average revenue per customer.
cogsSelf:=0.85*arpuSelf:
cogsPers:=arpuPers*0.85:
I didn't have enough time to put a simple exponential function instead of the randomizer,
so I put sigma to the minimal level and the number of scenarious to 1.
FCost[0]:= 3000: rfcost:= 0.02: sigmafcost:= 0.00001: N:= 48: M:= 1: T:= 48: h := T/N:

randomize():
U := RandomVariable(Normal(0, 1)):
W := exp((rfcost-(1/2)*sigmafcost^2)*h+sigmafcost*sqrt(h)*U):
SPr := [seq(Sample(W, N), i = 1 .. M)]:
for i to M do SPr[i][1] := FCost[0] end do:
SPr := map(CumulativeProduct, SPr):
Xrng := [seq(h*i, i = 1 .. N)]:
for k to N do
OpC[k]:=Mean([seq(SPr[i][k],i=1..M)])
end do:
The same with the depreciation. That's just an example. I recommend you to exclude this factor from the model, because it's not so important in case of an internet company at the early stage.
Dep[0]:= 250: rdep:= 0.005: sigmadep:= 0.00001: N:= 48: M:= 1000: T:= 48: h := T/N:
randomize():
U := RandomVariable(Normal(0, 1)):
W := exp((rdep-(1/2)*sigmadep^2)*h+sigmadep*sqrt(h)*U):
SPr := [seq(Sample(W, N), i = 1 .. M)]:
for i to M do SPr[i][1] := Dep[0] end do:
SPr := map(CumulativeProduct, SPr):
Xrng := [seq(h*i, i = 1 .. N)]:
for k to N do
Dep[k]:=Mean([seq(SPr[i][k],i=1..M)])
end do:
The amount of money we reinvest. Here is a weak place of the model. We can not reinvest with the negative cash flow. That's why it will be more correct to make a condition identical to the taxes calculator which will be further. I'll fix this bug pretty soon! :)
Cap[0]:= 30000: rcap:= 0.01: sigmacap:= 0.0001: N:= 48: M:= 1000: T:= 48: h := T/N:
randomize():
U := RandomVariable(Normal(0, 1)):
W := exp((rcap-(1/2)*sigmacap^2)*h+sigmacap*sqrt(h)*U):
SPr := [seq(Sample(W, N), i = 1 .. M)]:
for i to M do SPr[i][1] := Cap[0] end do:
SPr := map(CumulativeProduct, SPr):
Xrng := [seq(h*i, i = 1 .. N)]:
for k to N do
Cap[k]:=Mean([seq(SPr[i][k],i=1..M)])
end do:
with(SumTools):
r:=0.42/12:
k:=1:
In order to show the distribution of results there was a special function built called 'valuator'.
Valuator:=proc(i)local TotalCust, CustPers, CustSelf, SalesPers, SalesSelf, GrossMargin, OperatingProfit, OperatingProfitAT, tax, FCF, PV, PVn, PrVal;
global k,N,r, arpuPers, arpuSelf,cogsSelf,cogsPers,Visitors,Conv,AvPers,AvSelf,OpC,Cap;
for k to N do
Totalcust[k]:=abs(Visitors[i][k]*Conv[k]):
custPers[k]:=abs(Totalcust[k]*AvPers[k]):
custSelf[k]:=abs(Totalcust[k]*AvSelf[k]):
SalesPers[k]:=custPers[k]*arpuPers:
SalesSelf[k]:=custSelf[k]*arpuSelf:
GrossMargin[k]:=SalesPers[k]+SalesSelf[k]-cogsSelf*custSelf[k]-cogsPers*custPers[k]:
OperatingProfit[k]:=GrossMargin[k]-OpC[k]:
if (OperatingProfit[k] 0) then tax[k]:= OperatingProfit[k]*0.2: else tax[k]:=0 end if:
OperatingProfitAT[k]:=OperatingProfit[k]-tax[k]:

FCF[k]:= OperatingProfitAT[k]+Dep[k]-Cap[k]:
PV[k]:=FCF[k]/(1+r)^k:
end do:
PV[49]:=(PV[48]/(r-(0.05)/12))/(1+r)^48:
PVn:=[seq(PV[k],k=1..N)]:
DefiniteSummation(PV[t],t=1..N)+PV[49];
end proc:
Finally, we can build a histogram, illustrating the result.
with(Statistics):
q:=1:
M:=10000:
for q to M do
Value[q]:= Valuator(q):
end do:
ValueList:=[seq(Value[q],q=1..M)]:
with(Statistics):
A := ValueList:
B:=Mean(A);
Q := Histogram(A, averageshifted=3, color=grey, title="The value distribution according to 10 000 scenarious"):
plots[display](Q);

That's it!

No comments:

Post a Comment