linear response - defining the function

linearR <- function(x,a,b){
  # x : marketing input
  # a, b: coefficients
  q = a + b*x # quantity
  
  dqdx = rep(b, length(x))    # derivative (copies of a single value)
  #Diese Zeile berechnet die Ableitung (die Steigung) der Funktion. Bedeutung: Bei einer linearen Funktion q=a+b*x ist die Ableitung nach (x) immer der konstante Wert b. Code-Logik: rep(b, length(x)) erstellt einen Vektor, der den Wert b so oft wiederholt, wie x Datenpunkte hat. Es besagt: „Für jede Änderung von x ändert sich q um genau b Einheiten“.
  
  epsilon = b * x / q  # elasticity
  # berechnet die Punktelastizität
  #Da im vorherigen Schritt dq/dx=b festgelegt wurde, berechnet dieser Code, um wie viel Prozent sich die Menge q ändert, wenn x (z. B. der Preis) um 1 % steigt.Verhalten: Da x und q variieren, ist die Elastizität bei einer linearen Funktion nicht konstant, sondern ändert sich an jedem Punkt der Kurve.
  
return(list(q=q,dqdx=dqdx,epsilon=epsilon))
#Die Funktion gibt die Ergebnisse gebündelt in einer Liste zurück.
#Inhalt:
#q: Die berechneten Mengenwerte.
#dqdx: Die Grenzänderung (Steigung).
#epsilon: Die berechneten Elastizitäten für jeden Punkt.
  
}

multiplicative response - defining the function

multipR <- function(x,alpha,beta){
  # x : marketing input
  # alpha, beta: coefficients
  q = alpha * x^beta # quantity
  dqdx = alpha * beta * x^(beta - 1) # derivative
  epsilon = rep(beta, length(x)) # elasticity (copies of a single value)
  return(list(q=q,dqdx=dqdx,epsilon=epsilon))
}

a function to help us plot relationships

hilfplot <- function(input, x){
  #(input, x): Das sind die Platzhalter (Argumente). Die Funktion braucht zwei Dinge, um arbeiten zu können:
#input(input genannt, weil dieser Container die Daten sind, die in die Plot-Funktion hineingesteckt werden): Das Paket mit den berechneten Ergebnissen (wie die Menge q oder die Elastizität).
#x: Die ursprünglichen Datenpunkte (der Input-Vektor).
  par(mfrow = c(2,2))  
#Dieser Befehl bereitet das Grafikfenster darauf vor, mehrere Diagramme gleichzeitig anzuzeigen. 
#Bedeutung: Das Fenster wird in ein Raster aus 2 Zeilen und 2 Spalten unterteilt.
#Effekt: Die nächsten vier plot()-Aufrufe werden nicht nacheinander das Fenster überschreiben, sondern nebeneinander und untereinander in dieses Raster gefüllt. 

  
  # input versus quantity:
  
  plot(x,input$q, xlab = "input", ylab = "quantity", col="blue", lwd=2)
# x= Dies ist der Vektor der Eingangswerte (Input= werte die ich selber vorgebe).
#Es handelt sich um die unabhängige Variable (z. B. der Preis, die Werbeausgaben oder die Menge eines Rohstoffs), die du der Funktion hilfplot(input, x) als zweiten Parameter übergeben hast.
  #input$q (Die y-Achse / Vertikale)
#Bedeutung: Dies ist die berechnete Menge durch das modell (Quantity).
#input ist das Objekt, das die Ergebnisse deiner vorherigen Berechnung enthält.
  grid() #Dieser Befehl fügt dem aktuell aktiven Diagramm ein Hintergrundgitter (Koordinatennetz) hinzu. 
  #Zweck: Es erleichtert das Ablesen der Werte an den Achsen und macht Trends oder Muster im Diagramm besser sichtbar. 
  abline(0,1) # add a 45-degree line (may not be visible depending on the scaling)
  #Dieser Befehl zeichnet eine gerade Referenzlinie in das Diagramm.
  #Bedeutung: Die Zahlen stehen für a (Schnittpunkt mit der y-Achse) und b (Steigung).Effekt: Es wird eine 45-Grad-Winkelsymmetrale gezeichnet (startet bei 0,0 mit Steigung 1).Interpretation: In ökonomischen Modellen dient diese Linie oft als Referenz, um zu sehen, ob \(q\) schneller oder langsamer als der Input \(x\) wächst (z.B. um Skalenerträge zu visualisieren).
#col="blue": Die Datenpunkte oder Linien werden in Blau gezeichnet.
#lwd=2: Legt die Linienstärke fest (line width), hier doppelt so dick wie der Standard. 
  
  # input versus derivative:
  plot(x,input$dqdx, xlab = "input", ylab = "derivative", col="blue", lwd=2)
  grid() # add a grid to the plot
  abline(0,1) # add a 45-degree line (may not be visible depending on the scaling)

  # input versus elasticity:
  plot(x,input$epsilon, xlab = "input", ylab = "elasticity", col="blue", lwd=2)
  grid() # add a grid to the plot
  abline(0,1) # add a 45-degree line (may not be visible depending on the scaling)
  
}

using the functions to understand relationships between marketing inputs and outputs as a function of parameters

linear response

defining the input

x = seq(0,30,.5)  # creates a sequence starting at first entry, ending at second, increments defined in third entry # zahlenreihe erstellt und in der variable x gespeichert
a = 200 # konstante
b = 4 # steigung

calling the function

outLin=linearR(x,a,b)
#outLin= Output Linear
#linearR(...): Dies ist der Aufruf einer Funktion. Du sagst R: „Nimm die Formel für das lineare Modell und rechne sie jetzt aus.“ (Diese Funktion wurde wahrscheinlich weiter oben in deinem Skript mit linearR <- function(...) definiert).
#(x, a, b): Das sind die Zutaten (Argumente), die du der Funktion übergibst:

plotting the function output

hilfplot(outLin, x)

ASSIGNMENT 1:

play around with different parameter values to understand their relationship with demand

  1. if demand does not react to the x input at all, what does that imply for parameters “a” and “b”? R: “a” doesn’t matter, b equal to zero Wenn die Nachfrage gar nicht auf den Input x reagiert: Antwort: b muss gleich 0 sein.Intuition: Wenn b=0 ist, fällt der Term bx weg. Die Nachfrage bleibt immer gleich a, egal wie hoch x ist. Der Parameter a bestimmt dabei nur das konstante Niveau der Nachfrage.

  2. if demand is positively related to the input, what does that imply for parameters “a” and “b”? Wenn die Nachfrage positiv mit dem Input verknüpft ist: Antwort: b muss größer als 0 b>0 sein. a ist beliebig.Intuition: Ein positives b bedeutet: Wenn x steigt, wird ein positiver Wert dazuaddiert – die Nachfrage steigt (typisch z. B. für Werbeausgaben).

  3. if demand is negatively related to the input, what does that imply for parameters “a” and “b”? R: a doesn’t matter; positive relationship implies a positive b, negative relationship a negative b Wenn die Nachfrage negativ mit dem Input verknüpft ist: Antwort: b muss kleiner als 0 b<0 sein. a ist beliebig. Intuition: Ein negatives b bedeutet: Wenn x steigt, wird mehr von a abgezogen – die Nachfrage sinkt (typisch für den Preis).

  4. if demand is zero at zero input, what does that imply for parameters “a” and “b”? R: b doesn’t matter, a needs to be equal to zero Wenn die Nachfrage bei einem Input von Null ebenfalls Null ist: Antwort: a muss gleich 0 sein. b ist in diesem Moment beliebig. Intuition: Setzt man x=0 in die Gleichung ein, bleibt nur a übrig. Damit das Ergebnis Null ist, muss also a=0 gelten. Das bedeutet, die Kurve startet exakt im Ursprung des Koordinatensystems.

I don’t expect proofs, just your intuition form playing around with different parameter values

multiplicative response

defining the input

x = seq(.1,5,.1)  # creates a sequence starting at first entry, ending at second, increments defined in third entry
alpha = 3
beta = 2.0

calling the function

outMult=multipR(x,alpha,beta)

plotting the function output

hilfplot(outMult, x)

#ASSIGNMENT 2:

play around with different parameter values to understand their relationship with demand

  1. if demand does not react to the x input at all, what does that imply for parameters “alpha” and “beta”? R: alpha doesn’t matter, beta = 0

  2. if demand is positively related to the input, what does that imply for parameters “alpha” and “beta”?

  3. if demand is negatively related to the input, what does that imply for parameters “alpha” and “beta”? R: alpha doesn’t matter, positive beta implies a positive relation, negative beta a negative relation

  4. if demand is zero at zero input, what does that imply for parameters “alpha” and “beta”? R: for positive beta a zero input translates into zero output regardless of alpha and beta for negative beta, the output at zero input is not defined Wenn die Nachfrage bei einem Input von Null ebenfalls Null ist: Bei einem positiven beta führt ein Input von Null immer zu einer Nachfrage von Null, unabhängig von alpha. Bei einem negativen beta ist das Ergebnis bei Null mathematisch nicht definiert (Division durch Null).Erklärung:Ist beta >0 (z. B. D= alpha * x^2 ), dann ist 0^{2}=0. Die Kurve startet im Ursprung.Ist beta <0 (z. B. (D=alpha* x^{-1}) oder alpha/x, dann würde man durch Null teilen. Die Kurve nähert sich der y-Achse nur an (Asymptote), erreicht sie aber nie.

  5. how is the (absolute) elasticity related to the expected demand? R: elasticity is constant, no relationship to inputs or to demand as a function of inputs Wie hängt die (absolute) Elastizität mit der erwarteten Nachfrage zusammen? Die Elastizität ist in diesem Modell konstant und entspricht direkt dem Parameter beta. Es gibt keinen Zusammenhang zwischen der Elastizität und der Höhe des Inputs oder der daraus resultierenden Nachfrage.

  6. assuming positve beta, how does the demand curve change as beta

  1. approaches zero from above,
  2. approaches 1 from below,
  3. is larger than one?

R a) function becomes flat for all strictly positive inputs, there is a jump from zero input to some positive input

R b) you get a linear response

R c) curve becomes convex in marketing inputs

I don’t expect proofs, just your intuition form playing around with different parameter values

profit functions x::price

linear response

pi_linearR <- function(price,a,b,costs){
  # pi= Gewinn
  #price is the marketing input
  # costs are (constant) variable costs per unit sold
  out=linearR(price,a,b)
  #Das Programm „fragt“ diese Funktion: „Wie viele Einheiten verkaufe ich bei diesem Preis und diesen   Parametern?“ Das Ergebnis (die Menge) wird in der Variable out zwischengespeichert.
  out$q * (price - costs)
  #out$q: Greift auf die Menge (\(q\) für Quantity) zu, die im vorherigen Schritt berechnet     wurde.(price - costs): Berechnet die Gewinnspanne pro Stück (Verkaufspreis minus Herstellungskosten).
}

plot profits as a function of price

price = seq(1,30,.5)  # creates a sequence starting at first entry, ending at second, increments defined in third entry
a = 200
b = -5
costs = 2
 plot(price,pi_linearR(price,a,b,costs)); grid()

#plot(price, ...):
#Der plot-Befehl erstellt ein Koordinatensystem:
#Die x-Achse (waagerecht): Hier werden die Preise (price) von 1 bis 30 abgetragen.
#Die y-Achse (senkrecht): Hier wird das Ergebnis der Funktion abgetragen, also der berechnete Gewinn.

#Assignment 3:

  1. why are some profits negative? R: because price of 1 and 1.5 are below marginal costs of 2

  2. where is the profit maximizing price (approximately)? R: 21.5

…..what is the corresponding slope of the profit curve at this price? R: Slope at maximum is equal to zero

  1. how would fixed costs impact the pricing decision? R: no impact; but investment questionable if negative profits at optimal price Wie beeinflussen Fixkosten die Preisentscheidung? Antwort: Sie haben keinen Einfluss auf den optimalen Preis. Aber: Die Investition ist fragwürdig, wenn am Ende trotz optimalem Preis ein Verlust (negativer Profit) steht.Nur wenn die Fixkosten so hoch sind, dass du selbst am optimalen Punkt nur Minus machst, solltest du das Geschäft gar nicht erst betreiben.

  2. how is “b” directionally related to the profit maximizing price, everything else equal? R: more negative b (more price sensitive consumers), lower profit maximizing price Wie hängt “b” mit dem gewinnmaximalen Preis zusammen (alles andere bleibt gleich)? Je negativer b ist (je preisempfindlicher die Kunden sind), desto niedriger ist der gewinnmaximale Preis

multiplicative response

pi_multipR <- function(price,alpha,beta,costs){
  # price is the marketing input
  # costs are (constant) variable costs per unit sold
  out=multipR(price,alpha,beta)
  out$q * (price - costs)
}

plot profits as a function of price

price = seq(1.9,15,.1)  # creates a sequence starting at first entry, ending at second, increments defined in third entry
alpha = 3
beta = -1.8
costs = 2
 plot(price,pi_multipR(price,alpha,beta,costs)); grid()

#Assignment 4:

  1. why are some profits negative? R: because a price of 1.9 is below marginal costs

  2. where is the profit maximizing price (approximately)? What is the corresponding slope of the profit curve at this price? R: about 4.5; the corresponding profit is about .5 (note that alpha is a scaling factor here)

  3. how would fixed costs impact the pricing decision? R: no direct impact on pricing decision

  4. how is “beta” directionally related to the profit maximizing price, everything else equal? R: more negative beta, more price sensitive demand, lower profit maximizing price

  5. does alpha matter for the profit maximizing price? Why? Why not? R: no, it only scales demand but does not impact the profit maximizing price

  6. is there a profit maximizing price for beta larger/equal -1? R: no finite profit maximizing price exists anymore; if you find this in estimation, something is wrong

profit functions x::advertising dollars

linear response

pi_linearR <- function(adspend,a,b,price,costs){
  # adspend= Werbeausgaben
  #price is the marketing input
  # costs are (constant) variable costs per unit sold
  out=linearR(adspend,a,b)
  out$q * (price - costs) - adspend
}

plot profits as a function of adspend

adspend = seq(1,30,.1)  # creates a sequence starting at first entry, ending at second, increments defined in third entry
a = 200
b = 1.1
price = 3
costs = 2
 plot(adspend,pi_linearR(adspend,a,b,price,costs)); grid()

#Assignment 5: i) what is the optimal adspend for b smaller / larger 1? Why? R: the optimal adspend for b>1 contribution margin is infinity because each money unit invested in advertising returns more than that unit the optimal adspend for b < 1 contribution margin is zero because each money unit invested in advertising returns less than that unit Werbung “lohnt sich”: Dann mache so viel wie möglich (unendlich). Werbung “lohnt sich nicht”: Dann mache gar nichts (null).

multiplicative response

pi_multipR <- function(adspend,alpha,beta,price,costs){
  # price is the marketing input
  # costs are (constant) variable costs per unit sold
  out=multipR(adspend,alpha,beta)
  out$q * (price - costs) - adspend
}

plot profits as a function of price

adspend = seq(.1,20,.1)  # creates a sequence starting at first entry, ending at second, increments defined in third entry
alpha = 3
beta = .7
price = 3
costs = 2
 plot(adspend,pi_multipR(adspend,alpha,beta,price,costs)); grid()

#Assignment 6: i) how is the optimal adspend directionally related to beta?

using R’s optimizer (comparable to Excel’s solver) to find the optimal advertising budget in the above example

out=optim(par=2, #starting value; NEEDS TO BE FIRST ARGUMENT of target function (see next line)
          fn=pi_multipR,  #function that return *scalar* target value
          gr=NULL,  #could provide gradient information, did not here
          alpha=alpha, #additional inputs to target funtion
          beta=beta, #additional inputs to target funtion
          price=price, #additional inputs to target funtion
          costs = costs, #additional inputs to target funtion
          hessian = TRUE, #return numerical hessian (2nd derivative) at the optimum
          control=list(fnscale=-1),  #maximize instead of minimization
          method = "Brent",  #optimal method for optimizing a scalar input
          lower = 0, upper = 6000 #search interval for optimizer
          )

out
## $par
## [1] 11.85944
## 
## $value
## [1] 5.082619
## 
## $counts
## function gradient 
##       NA       NA 
## 
## $convergence
## [1] 0
## 
## $message
## NULL
## 
## $hessian
##            [,1]
## [1,] -0.0252963
#Die Funktion optim ist ein "Suchroboter". Sie probiert verschiedene Werte aus, um den besten Wert (das Optimum) für eine Funktion zu finden. In diesem Fall sucht sie den Adspend, der den Gewinn maximiert.
# par=2 : bei wert 2 anfangen zu testen
#Die Ziel-Funktion(fn=pi_multipR): Das ist das Rezept, das optimiert werden soll. pi_multipR berechnet den Gewinn. Der Roboter wird diese Funktion immer wieder mit verschiedenen Zahlen füttern, um zu sehen, wann das Ergebnis am größten ist.
#Gradient: Hier könnte man mathematische Ableitungen angeben, um dem Roboter die Richtung zu zeigen. NULL bedeutet: „Brauchst du nicht, such einfach so.
#Krümmung (Hessian): Wenn dies auf TRUE steht, gibt der Computer am Ende eine Info über die Krümmung der Kurve am optimalen Punkt aus. Das hilft zu verstehen, wie "stabil" das Maximum ist.
#Maximieren statt Minimieren: Standardmäßig sucht optim immer das Minimum (den tiefsten Punkt). Da wir aber den maximalen Gewinn suchen, sagt fnscale=-1 dem Computer: „Dreh das Ergebnis um, wir wollen zum höchsten Punkt!
#Die Such-Methode: "Brent" ist ein spezieller, sehr schneller Rechenweg (Algorithmus). Er ist besonders gut geeignet, wenn man nur eine einzige Zahl sucht (hier: den optimalen Adspend).

checking the solution graphically

plot(adspend,pi_multipR(adspend,alpha,beta,price,costs)); grid()
abline(v=out$par, lwd=2, col="red")  # the input value that maxmimizes the function
abline(h=out$value, lwd=2, col="red") # the value of the function at the maximum

#Assignment 7: i) compute the profit maximizing price in the following setting using the optimizer

profit functions x::price

linear response

pi_linearR <- function(price,a,b,costs){
  # price is the marketing input
  # costs are (constant) variable costs per unit sold
  out=linearR(price,a,b)
  out$q * (price - costs)
}

plot profits as a function of price

price = seq(1,30,.5)  # creates a sequence starting at first entry, ending at second, increments defined in third entry
a = 200
b = -5
costs = 2
 plot(price,pi_linearR(price,a,b,costs)); grid()

Demonstrate optimization in multiple variables (as in Bernd Skiera’s preparation video for today)

initialize coefficients (as estimated in the log-log regression model)

beta=matrix(
  c( 16.9806610,       -2.3394800,        0.3995158,        0.2168935),
  ncol=4)
#matrix(c(...), ncol=4): Hier werden vier Zahlen in einer Reihe (1 Zeile, 4 Spalten) zusammengefasst.
colnames(beta) = c('alpha', 'beta-price', 'beta-person', 'beta-advertising')
# Hier gibt man den Spalten namen
costs=matrix(c(30, 120000), ncol = 2)
#Hier werden zwei verschiedene Arten von Kosten definiert:
#30: Die variablen Stückkosten (z. B. Materialkosten pro Produkt).
#120.000: Die Fixkosten für eine Person (z. B. Jahresgehalt eines Vertriebsmitarbeiters)
colnames(costs) = c('marginal unit costs', 'costs per salesperson')

define response and profit function

Note that we can work with almost (!) the same response function as defined above b/c of how R automatically handles vectors. However, it’s always a good, life-saving idea to check if R’s automatic defaults accomplish what you actually want to do

multipR <- function(x,alpha,beta){
  # x : marketing input
  # alpha, beta: coefficients
  #q = alpha * x^beta # quantity
  q = exp(alpha +  beta%*% log(x)) # quantity; recall that the log-log regression yields log(alpha)!!
  # alternatively: q = exp(alpha) * prod(x^beta) # quantity; recall that the log-log regression yields log(alpha)!!
  dqdx = exp(alpha) * beta * x^(beta - 1) # derivative
  epsilon = beta  # elasticities (copies of a single value)
  return(list(q=q,dqdx=dqdx,epsilon=epsilon))
}

pi_multipR <- function(logx,alpha,beta,costs){
  # price, salespeople, and adspend as marketing inputs in the *vector* x (order as in the beta coefficient vector
  # ....defined above)
  # costs is two element vector; the first entry are (constant) variable costs per unit sold, the second entry
  # ....are the costs per salesperson
  x=exp(logx)
  price = x[1]
  persons = x[2]
  adspend = x[3]
  out=multipR(x,alpha,beta)
  out$q * (price - costs[1]) - adspend - persons*costs[2]
}

the call to the optimizer

out=optim(par=c(log(29),log(20),log(5000)), #starting value; NEEDS TO BE FIRST ARGUMENT of target function (see next line)
          fn=pi_multipR,  #function that return *scalar* target value
          gr=NULL,  #could provide gradient information, did not here
          alpha=beta[1], #additional inputs to target function
          beta=beta[2:4], #additional inputs to target function
          costs = costs, #additional inputs to target function
          hessian = TRUE, #return numerical hessian (2nd derivative) at the optimum
          control=list(fnscale=-1)  #maximize instead of minimization
          # method = "BFGS"  #a quasi-Newton method (also known as a variable metric algorithm), uses function values and gradients to build up a picture of the surface to be optimized.
          )

out
## $par
## [1]  3.958969  1.614296 12.698817
## 
## $value
## [1] 579033.1
## 
## $counts
## function gradient 
##      168       NA 
## 
## $convergence
## [1] 0
## 
## $message
## NULL
## 
## $hessian
##               [,1]         [,2]         [,3]
## [1,] -4727568.7449    -234.4743    -127.2939
## [2,]     -234.4743 -362016.1886  130785.7939
## [3,]     -127.2939  130785.7939 -256357.9771
exp(out$par)
## [1] 5.240329e+01 5.024352e+00 3.273603e+05