Learn R Programming

AssetPricing (version 0.0-10)

xsolve: Optimal pricing policy

Description

Determines (by solving a coupled system of differential equations) the optimal prices as functions of (residual) time for a number perishable assets. Prices may be discrete or continuous. For continuous prices, the price sensitivity function may either be a smooth (twice differentiable) function or a function which is piecewise linear in price.

Usage

xsolve(S, lambda, gprob=1, tmax=NULL, qmax, prices=NULL, nstep, type="sip",
                   alpha=NULL, salval=0, maxFac=1000, nverb=0)

Arguments

S
An expression, or list of expressions, or a function or list of functions, specifying the price sensitivity functions S_j(x,t). See Details.
lambda
A function (of residual time t --- see tmax) or a positive constant, specifying the intensity of the (generally inhomogeneous) Poisson process of arrival times of groups of potential customers.
gprob
A function (to calculate probabilities) or a numeric vector of probabilities determining the distribution of the size of an arriving group of customers.
tmax
The maximum residual time; think of this as being the initial time at which the assets go on sale (with time decreasing to zero, at which point the value of each asset drops to the salvage value (salval), usual
qmax
The maximum number of assets available for sale, i.e. the number of assets available at the starting (residual) time tmax.
prices
A numeric vector (with positive values) listing the possible prices at which items may be offered for sale in the discrete pricing scenario.
nstep
The number of (equal) sub-intervals into which the interval [0,tmax] is divided in the process of solving the system of differential equations numerically.
type
Scalar character string taking one of the two values "sip" (singly indexed prices) and "dip" (doubly indexed prices). In the "dip" case the price of the asset which is quoted to the arriving group is allowed to
alpha
A numeric scalar between 0 and 1 specifying the probability that an arriving group of size j > q (where q is the number of assets remaining for sale) will consider purchasing (all of) these remaining assets. It is
salval
A (non-negative) numeric scalar specifying the salvage value of an asset --- i.e. the quantity to which the value of an asset drops at residual time t=0. Usually salval is equal to 0.
maxFac
A (positive) numeric scalar used in determining the optimal price in settings in which this involves maximizing over a discrete set. See Details. Ignored if the price sensitivity function is smooth.
nverb
Non-negative integer; if nverb > 0 then a progress report (actually consisting solely of the step number) is printed out every nverb steps of the Runge-Kutta procedure. (If nverb==0 the procedu

Value

  • A list with components:
  • xThe optimal pricing policy, chosen to maximize the expected value of the remaining assets at any given time; an object of class flap (function list for asset pricing). (In the case of discrete prices it also inherits from pwc.flap (pwc stands for piecewise constant), and if type=="dip" it also inherits from di.flap.) It has the form of a list of functions x_q(t), with q running from 1 to qmax if type=="sip". If type=="dip" if has the form of a list of functions x_qj(t) with q running from 1 to qmax and j running from 1 to min(q,jmax) where jmax is the maximum group size.

    In the case of continuous prices these functions will be continuous functions created by splinefun(). In the case of discrete prices these functions will be piecewise constant (of class stepfun) created by stepfun().

    Note that x has an attribute qmax specifying the maximum number of assets available for sale, i.e. the number of assets available at the starting (residual) time tmax. Of course if type=="sip" then this attribute is simply the length of x. Note that if type == "dip" then the entry x[[i]] is equal to the function x_qj(t) where i = (j-1)*(qmax - j/2) + q.

  • vAn object of class flap whose entries are (spline) functions v_q(t) specifying the (optimal) expected value of q assets at time t corresponding to the (optimal) pricing policy x.
  • vdotAn object of class flap whose entries are the derivatives (with respect to t) of the functions v_q(t) described above. The values of these derivatives are determined sequentially in the process of solving the system of differential equations for the optimal pricing policy.

Details

If prices are modelled as being continuous, and if the price sensitivity function is differentiable, a coupled system of differential equations for the optimal prices is solved. If the prices are modelled as being discrete or if the price sensitivity function is piecewise linear in price, then a coupled system of differential equations for the expected value of the stock is solved, with the optimal price being determined at each step by maximizing over an appropriate finite discrete set. The systems of differential equations are treated in vectorised form and are solved via the method of Runge-Kutta.

The components of the argument S should be provided as expressions when the price sensitivity functions are assumed to be smooth, and these should be amenable to differentiation with respect to x and t via the function deriv3().

Note that in general the expression or expressions will depend upon a number of parameters as well as upon x and t. The values of these parameters are specified via an attribute or attributes. If S is a (single) expression it has (must have) an attribute called parvec which is a named vector of parameter values. If S is a list of expressions each entry of the list has (must have) such an attribute.

In the piecewise linear context S can be specified only as a single function. It is then assumed that the price sensitivity function for a group of size j is given by S_j(x,t) = S(x,t)^j. Such piecewise linear price sensitivity functions should be built using the function buildS().

In the case of discrete prices the argument S must be a function or list of functions specifying the price sensitivity functions S_j(x,t). These functions need only be defined for the prices listed in the prices argument.

If S is a single expression or function, then S_j(x,t) is taken to be this expression or function raised to the power j. If S is a list, then S_j(x,t) is taken to be its j-th entry.

For discrete prices and for piecewise linear price sensitivity functions, determining the optimal price involves maximizing expected values over finite discrete sets. It can happen that there are a number of values close to the maximum, and as a consequence the location of the maximum can make a sudden jump from one time step to the next, causing anomalous looking discontinuities in the optimal price functions. To avoid this, the optimal price is chosen to be that one from among a suitable subset of the candidate prices which is closest to the price at the previous time step.

The subset consists of those prices yielding expected values which are within $\epsilon$ of the maximum. Here $\epsilon$ is equal to the range (i.e. max minus min) of the possible expected values, divided by maxFac. Setting maxFac=Inf has the effect of simply picking the maximal value (or the first maximal value if there are a number of such values that are numerically equal). Using different values of maxFac may have an impact on the optimal price functions but will generally have little or no discernible impact on the corresponding expected values of stocks.

In the case where argument S is a piecewise linear price sensitivity function, the argument tmax is, if not specified, taken to be the value of the corresponding attribute of S. In this setting, if tmax is specified it must be less than or equal to the corresponding attribute of S.

References

Banerjee, P. K. and Turner, T. R. A flexible model for the pricing of perishable assets. Omega, vol. 40, number 5, 2012, pages 533 -- 540, doi: 10.1016/j.omega.2011.10.001.

See Also

vsolve(), plot.flap(), buildS()

Examples

Run this code
#
# In these examples "nstep" has been set equal to 100
# to reduce the time for package checking on CRAN.
# A more "realistic" value is nstep=1000.  Likewise "qmax"
# has been set equal to 5 which is an unrealistically low
# value for the total number of assets.
#
# Smooth price sensitivity function.
S <- expression(exp(-kappa*x/(1+gamma*exp(-beta*t))))
attr(S,"parvec") <- c(kappa=10/1.5,gamma=9,beta=1)

# Optimal pricing policy assuming customers arrive singly:
lambda1 <- function(tt){
	84*(1-tt)
}
X1 <- xsolve(S=S,lambda=lambda1,gprob=1,tmax=1,qmax=5,nstep=100,
             type="sip",nverb=50)
# Optimal pricing policy assuming customers arrive in groups of
# size up to 5, with group size probabilities 1/3, 4/15, 1/5, 2/15,
# and 1/15 respectively.
lambda2 <- function(tt){
	36*(1-tt)
}
X2 <- xsolve(S=S,lambda=lambda2,gprob=(5:1)/15,tmax=1,qmax=5,nstep=100,
             type="sip", alpha=0.5,nverb=50)

# Note that the intensity functions lambda1() and lambda2() are
# such that the expected total number of customers is 42 in each case.

# Discrete prices:
lambda3 <- function(t){42}
S      <- function(x,t){
                e <- numeric(2)
                e[x==1] <- exp(-2*t)
                e[x==0.6] <- 1.0
                e
          }
X3 <- xsolve(S=S,lambda=lambda3,gprob=1,tmax=1,qmax=5,prices=c(1,0.6),
             nstep=100,type="sip",nverb=50)

# Piecewise linear price sensitivity function.
#
# Take S as in the example for buildS.
# This takes a loonnngggg time; the procedure is slow
# in the piecewise linear setting.
l0 <- get("lambda",envir=environment(get("alpha",envir=environment(S))[[1]]))
lambda4 <- function(t){apply(l0(t),1,sum)}
X4 <- xsolve(S=S,lambda=lambda4,gprob=(5:1)/15,qmax=30,nstep=1000,type="sip",
                   alpha=0.5,nverb=50)

Run the code above in your browser using DataLab