The goal of clptheory (classical price theory)
is to create a suite of functions to implement the classical theory of
prices. The functions in this package computes the uniform rate of
profit, the vector of price of production (PP), the vector of direct
prices (DP) and the vector of labor values for the circulating capital
model and the capital stock model. The functions also computes various
non-regression-based measures of deviation between PP/MP, DP/MP and
PP/DP, where MP denotes the vector of market prices (which is a vector
of 1s).
You can install the package clptheory from CRAN
with:
# Uncomment the following line
# install.packages("clptheory")You can install the development version of clptheory
from GitHub with:
# Uncomment the following two lines
# install.packages("devtools")
# devtools::install_github("dbasu-umass/clptheory")This package provides the following functions.
ppstdint1: a function to estimate a basic
circulating capital model with the Standard Interpretation
(SI);
ppstdint2: a function to estimate a basic capital
stock model with the Standard Interpretation (SI);
ppnewint1: a function to estimate a basic
circulating capital model with the New Interpretation (NI);
ppnewint2: a function to estimate a basic capital
stock model with the New Interpretation (NI);
ppsraffa1: a function to estimate a circulating
capital model with the Sraffian approach;
nonregdist: a function that computes various
non-regression-based measures of deviation between the vector of prices
of production, the vector of market prices and the vector of direct
prices (labor values);
createdata: a function to create the data objects
(matrices, vectors and scalars) necessary to implement the SI and NI
using basic data from the World Input Output Database (WIOD).
The package contains the following data sets.
aussea: the socio-economic accounts (SEA) for the
Australian economy extracted from the 2016 release of WIOD; this data
set contains industry-level variables (53 industries) for the USA for 15
years, 2000-2014;
ausiot: input-output (IO) tables for the Australian
economy extracted from the 2016 release of the World Input Output
Database; this data set contains 53-industry input-output tables for the
USA for 15 years, 2000-2014;
usasea: the socio economic accounts (SEA) for the
USA extracted from the 2016 release of the World Input Output Database;
this data set contains industry-level variables (53 industries) for the
USA for 15 years, 2000-2014;
usaiot: input-output tables for the USA extracted
from the 2016 release of the World Input Output Database; this data set
contains 53-industry input-output tables for the USA for 15 years,
2000-2014;
usarwb: personal consumption expenditure on the
output of the 53 industries of the input-output tables for the USA
extracted from the 2016 release of the World Input Output Database; this
data set contains data for 15 years, 2000-2014. (Note: This data set is
not necessary for the analysis.)
To see the correct syntax, the required inputs and the output of the
functions, use the help function in R.
Let us conduct price of production analysis for the USA and see how
to use the functions in clptheory to:
compute the uniform rate of profit and the vectors of labor values and prices of production for a basic circulating capital model using the Standard Interpretation and the New Interpretation; and
compute various non-regression-based measures of deviation between PP/MP, DP/MP and PP/DP.
Let us load the package.
# Load library
library(clptheory)Let us create the data objects from the WIOD data base using the
createdata function. To use this function, the user needs
to supply the name of the country code (in this case “USA”), the year
(in this case 2010), the name of the SEA data set (in this case
usasea) and the name of the IO data set (in this case
usaiot).
usadata <- clptheory::createdata(
country = "USA", year = 2010,
datasea = usasea, dataio = usaiot
)
#> "U"Let us now estimate the circulating capital model with SI with the
ppstdint1 function. To use this function, the user needs to
supply the A (input-output) matrix, the b (real wage bundle) vector, the
Q (gross output) vector, and the labor input (simple labor) vector.
These are supplied as elements of the list usadata created
by the createdata function.
There are at least two different ways in which the real wage bundle (vector) can be computed. The first method, which is more common in the SI literature, is to compute it as the product of the vector of shares of personal consumption expenditure (PCE) and the minimum wage rate (which is a scalar); the second method, which is equally intuitive, is to compute it as the vector of total PCE divided by the total hours of work (which is a scalar). We implement both these definitions below.
si1 <- clptheory::ppstdint1(
A = usadata$Ahat,
# real wage bundle = vector of share of PCE * min wage
b = usadata$b1,
Q = usadata$Q,
l_simple = usadata$l_simple
)
si2 <- clptheory::ppstdint1(
A = usadata$Ahat,
# real wage bundle = vector of PCE / total labor hours
b = usadata$b,
Q = usadata$Q,
l_simple = usadata$l_simple
)Let us now estimate the circulating capital model with NI with the
ppnewint1 function. To use this function, the user needs to
supply the A (input-output) matrix, the average nominal wage rate
(scalar), the v (value of labor power) scalar, the Q (gross output)
vector, and the labor input (simple labor) vector. These are supplied as
elements of the list usadata created by the
createdata function.
ni1 <- clptheory::ppnewint1(
A = usadata$Ahat,
w = usadata$wavg,
v = usadata$vlp,
Q = usadata$Q,
l_simple = usadata$l_simple
)Let us compare the uniform profit rates from SI and NI.
cbind(si1$urop,si2$urop,ni1$urop)
#> [,1] [,2] [,3]
#> [1,] 0.5463579 -0.2816745 0.3709973Here we see that the uniform rate of profit estimated by the SI and NI, respectively, are 54.64 percent, -28.17 percent and 37.10 percent. Thus, computing the real wage bundle as the vector of PCE divided by total hours of work gives rise to a negative uniform rate of profit in the SI.
Let us investigate why the uniform rate of profit computed from the SI is negative. Recall that the uniform rate of profit computed from the SI is \((1/\lambda(M))-1\), where \(M=A+bl\) is the augmented input matrix and \(\lambda(M)\) is the maximal eigenvalue of \(M\). Thus, the uniform rate of profit is negative when \((1/\lambda(M))<1\), that is, when \(\lambda(M)>1\) (the matrix \(M\) is not productive). We can check this from the output of the SI:
# maximal eigenvalue of M
(si2$meig)
#> [1] 1.392127Thus, we see that the maximal eigenvalue of \(\lambda(M)\) is 1.392, which
is indeed larger than \(1\). Let us
first check whether the conditions for applying the Perron-Frobenius
theorem valid?
# Is M nonnegative (1=Y)
(si2$Mnonneg)
#> [1] 1
# Is M irreducible (1=Y)
(si2$Mirred)
#> [1] 1Yes, the conditions are satisfied: \(M\) is nonnegative and irreducible.
Our conjecture is that the negative uniform rate of profit arises
because the real wage bundle b is too large,
i.e. so large as to make the matrix \(M\) non-productive (see page 349-50 in
Basu, 2021). We can check this indirectly by checking whether
the maximum profit rate, \(R\), is
positive because \(R=(1/\lambda(A))-1\), where \(\lambda(A)\) is the maximal eigenvalue of
the input-output matrix \(A\).
# maximal rate of profit
(si2$mrop)
#> [1] 1.557706Here we see that \(R\) is positive, which implies that $(A)<1 so that the matrix \(A\) is productive. Hence, our conjecture seems to be correct: a large real wage bundle is driving down the uniform rate of profit to negative territory.
At this point, it is pertinent to point out that the method of computing the uniform profit rate in the SI does not per se ensure that the uniform rate of profit is positive. It depends on how the real wage bundle (vector) is computed. In fact, We have just seen a case where the uniform rate of profit is negative (when the real wage bundle is computed as the vector of PCE per hour of work). On the other other hand, the computation of the uniform rate of profit in the NI ensures that the answer is always positive (see page 353-55 in Basu, 2021). This is one advantage of using the NI over the SI.
Let us compute various non-regression-based measures of the deviation
between PP/MP, DP/MP and PP/DP for the SI using the
nonregdist function. To use this function, the user must
supply the price of production vector (in this case
si1$pp), the direct prices vector (in this case
si1$dp), the vector of nominal wage rates (in this case
usadata$wagevector_all), the average wage rate as a scalar
(in this case usadata$wavg) and the gross output vector (in
this case usadata$Q). These are supplied as elements of the
list si1 created by the ppstdint1 function and
elements of the list usadata created by the
createdata function.
nrsi1 <- clptheory::nonregdist(
x = si1$pp,
y = si1$dp,
w = usadata$wagevector_all,
w_avg = usadata$wavg,
Q = usadata$Q
)Let us do the same computation for the NI. Here, the necessary inputs
are supplied as elements of the list ni1 created by the
ppnewint1 function and elements of the list
usadata created by the createdata
function.
nrni1 <- clptheory::nonregdist(
x=ni1$pp,
y=ni1$dp,
w=usadata$wagevector_all,
w_avg=usadata$wavg,
Q=usadata$Q
)We can now compare the results for the analysis of the circulating capital model from the SI approach and the NI approach for the non-regression-based measures of deviation between PP/MP, DP/MP and PP/DP.
# bring the results together
comp1 <- cbind(nrsi1,nrni1)
# provide column names to identify the methodology, i.e. SI or NI
colnames(comp1) <- c("SI","NI")
# provide rownames to identify measures
rownames(comp1) <- c(
"RMSE_PPMP", "RMSE_DPMP","RMSE_PPDP",
"MAD_PPMP", "MAD_DPMP","MAD_PPDP",
"MAWD_PPMP", "MAWD_DPMP","MAWD_PPDP",
"Angle_PPMP", "Angle_DPMP","Angle_PPDP",
"DDist_PPMP", "DDist_DPMP","DDist_PPDP"
)
# ---- The results
(comp1)
#> SI NI
#> RMSE_PPMP 0.230377 1.774267
#> RMSE_DPMP 0.2818772 0.2818772
#> RMSE_PPDP 0.1816673 1.649635
#> MAD_PPMP 0.1888116 1.677533
#> MAD_DPMP 0.229908 0.229908
#> MAD_PPDP 0.1359609 1.623438
#> MAWD_PPMP 0.2324022 1.575482
#> MAWD_DPMP 0.2925821 0.2925821
#> MAWD_PPDP 0.1547199 1.639208
#> Angle_PPMP 12.13116 12.59748
#> Angle_DPMP 15.15651 15.15651
#> Angle_PPDP 9.671902 6.429343
#> DDist_PPMP 0.2113334 0.2194249
#> DDist_DPMP 0.2637604 0.2637604
#> DDist_PPDP 0.1686062 0.1121543In the results above, we see the magnitudes of six different measures of the deviation between PP/MP, DP/MP, PP/DP: root mean squared error (RMSE), mean absolute distance (MAD), mean absolute weighted distance (MAWD), angle between the two vectors (angle in degrees), and the d-distance computed using angle (distance).
As an example, we can see that the d-distance of the deviation between PP/MP, DP/MP, PP/DP for SI are 0.211, 0.264 and 0.169, respectively. This can be interpreted as showing that the deviation between PP/MP, DP/MP, PP/DP are 21.1 percent, 26.4 percent and 16.9 percent, respectively. The corresponding measures of deviation for NI are 0.219, 0.264 and 0.112, respectively.
A reader might be puzzled to note that the measure of deviation for DP/MP are the same in both SI and NI. The reason for this is as follows: the DP vector is just a re-scaled value of the labor value vector. The calculation of the labor value vector is the same in both SI and NI. The MP vector is just a vector of 1s. Hence, this vector is also same for both SI and NI.
Let us compute the uniform rate of profit using the SI and NI for the USA for several years. To do so, we will write some code to loop over all the years in the data set: 2000-2014, i.e. 15 years.
# matrix to store results
urop <- matrix(NA, nrow = 15, ncol = 3)
# for loop
for(i in 1:15){
# read data
usadata <- clptheory::createdata(
country = "USA", year = (1999+i),
datasea = usasea, dataio = usaiot
)
# estimate SI
si1 <- clptheory::ppstdint1(
A = usadata$Ahat,
b = usadata$b1,
Q = usadata$Q,
l_simple = usadata$l_simple
)
# estimate NI
ni1 <- clptheory::ppnewint1(
A = usadata$Ahat,
w = usadata$wavg,
v = usadata$vlp,
Q = usadata$Q,
l_simple = usadata$l_simple
)
# store result on the uniform rate of profit
urop[i,] <- c(1999+i,si1$urop,ni1$urop)
}Now let us see the results
# convert matrix of results to a data frame
urop_result <- as.data.frame(urop)
# supply column names
colnames(urop_result) <- c("year","urop(SI)","urop(NI)")
# print results
(urop_result)
#> year urop(SI) urop(NI)
#> 1 2000 0.4537127 0.2858142
#> 2 2001 0.4623717 0.2891242
#> 3 2002 0.4832424 0.3135421
#> 4 2003 0.4915553 0.3223199
#> 5 2004 0.4955940 0.3296036
#> 6 2005 0.5017683 0.3336100
#> 7 2006 0.5067786 0.3414167
#> 8 2007 0.4932053 0.3248530
#> 9 2008 0.4975868 0.3087132
#> 10 2009 0.5374173 0.3494991
#> 11 2010 0.5463579 0.3709973
#> 12 2011 0.5390641 0.3584673
#> 13 2012 0.5328071 0.3556414
#> 14 2013 0.5291820 0.3595651
#> 15 2014 0.5159078 0.3530419
# standard deviation of urop: SI
stats::sd(urop_result[,c("urop(SI)")])
#> [1] 0.02775876
# standard deviation of urop: NI
stats::sd(urop_result[,c("urop(NI)")])
#> [1] 0.02586745From the last two lines above, we see that the uniform rate of profit estimated by the SI has similar variability as the uniform rate of profit estimated by the NI. Moreover, the uniform rate of profit estimated by the SI is negative for all years!
Let us compute the uniform rate of profit using the SI and NI for Australia for several years. Just like in the case of the USA, we will write some code to loop over all the years in the data set: 2000-2014, i.e. 15 years.
# matrix to store results
urop <- matrix(NA, nrow = 15, ncol = 3)
# for loop
for(i in 1:15){
# read data
ausdata <- clptheory::createdata(
country = "AUS", year = (1999+i),
datasea = aussea, dataio = ausiot
)
# estimate SI
si1 <- clptheory::ppstdint1(
A = ausdata$Ahat,
b = ausdata$b1,
Q = ausdata$Q,
l_simple = ausdata$l_simple
)
# estimate NI
ni1 <- clptheory::ppnewint1(
A = ausdata$Ahat,
w = ausdata$wavg,
v = ausdata$vlp,
Q = ausdata$Q,
l_simple = ausdata$l_simple
)
# store result on the uniform rate of profit
urop[i,] <- c(1999+i,si1$urop,ni1$urop)
}Now let us see the results
# convert matrix of results to a data frame
urop_result <- as.data.frame(urop)
# supply column names
colnames(urop_result) <- c("year","urop(SI)","urop(NI)")
# print results
(urop_result)
#> year urop(SI) urop(NI)
#> 1 2000 1.5308253 0.4383862
#> 2 2001 1.8481513 0.4850732
#> 3 2002 1.7031252 0.4756530
#> 4 2003 1.2458479 0.4691115
#> 5 2004 0.9934422 0.4133871
#> 6 2005 0.9331798 0.4012927
#> 7 2006 0.9631239 0.4122654
#> 8 2007 0.7701843 0.3746102
#> 9 2008 0.7694284 0.3770067
#> 10 2009 0.8928096 0.4022079
#> 11 2010 0.6229650 0.3485714
#> 12 2011 0.4590227 0.3101514
#> 13 2012 0.4658874 0.3138961
#> 14 2013 0.5718644 0.3328282
#> 15 2014 0.6846815 0.3607879
# standard deviation of urop: SI
stats::sd(urop_result[,c("urop(SI)")])
#> [1] 0.4360764
# standard deviation of urop: NI
stats::sd(urop_result[,c("urop(NI)")])
#> [1] 0.05632964From the last two lines, we now see that the uniform rate of profit estimated by the SI has much higher variability than the uniform rate of profit estimated by the NI.
This simple example of a capital stock model was presented on pages 46-57 of E. M. Ochoa’s dissertation (Ochoa, E. M. 1984. Labor-Value and Prices of Production: An Interindustry Study of the U.S. Economy, 1947–1972. PhD thesis, New School for Social Research, New York, NY.).
Let us create the data set for this example following pages 46-57 of Ochoa (1984).
# Input-output matrix
A <- matrix(
data = c(0.265,0.968,0.00681,0.0121,0.391,0.0169,0.0408,0.808,0.165),
nrow=3, ncol=3, byrow = TRUE
)
# Depreciation matrix
D <- matrix(
data = c(0,0,0,0.00568,0.0267,0.0028,0.00265,0.0147,0.00246),
nrow=3, ncol=3, byrow = TRUE
)
# Direct labor input vector
l <- matrix(
data = c(0.193, 3.562, 0.616),
nrow=1
)
# Real wage bundle vector
b <- matrix(
data = c(0.0109, 0.0275, 0.296),
ncol=1
)
# Gross output vector
Q <- matrix(
data = c(26530, 18168, 73840),
ncol=1)
# Capital stock coefficient matrix
K <- matrix(
data = c(0,0,0,0.120,0.791,0.096,0.037,0.251,0.043),
nrow=3, ncol=3, byrow = TRUE
)
# Diagonal matrix of turnover times
t <- diag(c(0.317, 0.099, 0.187))
# average nominal wage rate
wavg <- 3.765
# Vector of nominal wage rates
w <- matrix(
data = rep(wavg,3),
ncol = 1
)
# Value of labor power
v <- 2/3
# Matrix of tax rates (assumed 0)
Tax <- matrix(0,nrow=3,ncol=3)We will first now implement the classical theory of prices for the capital stock model.
# Estimate model
si2 <- ppstdint2(
A = A,
l = l,
b = b,
Q = Q,
D = D,
K = K,
t = t,
Tax = Tax
)What is the uniform rate of profit?
si2$urop
#> [1] 0.2337492This exactly matches what is reported in equation (37) on page 57 in Ochoa (1984).
Now let us compute the vector of labor values:
si2$lvalues
#> [,1] [,2] [,3]
#> [1,] 0.5192079 8.309406 0.9407729This is exactly equal to what is reported in equation (11) on page 47 in Ochoa (1984).
What is the vector of direct prices?
si2$dp
#> [,1] [,2] [,3]
#> [1,] 0.2627846 4.205606 0.4761495These are different from what is reported in equation (12) on page 48
in Ochoa (1984). The reason for this difference is that he uses a vector
of market prices, (4, 60, 7) for normalization that is
different from a vector of 1s (which is the common assumption in real
world analysis). To use Ochoa’s vector of market prices, we can do the
following:
# vector of market prices
mktp <- c(4,60,7)
# normalization factor: kappa
mykappa <- sum(mktp*as.vector(Q))/sum(as.vector(si2$lvalues)*as.vector(Q))
# renormalize direct prices
si2$dp <- mykappa * si2$lvalues
# see new vector of direct prices
(si2$dp)
#> [,1] [,2] [,3]
#> [1,] 3.797694 60.77831 6.881188Now we have the exact vector of direct prices reported in equation (12) on page 48 in Ochoa (1984).
What is the vector of prices of production?
si2$pp
#> [1] 0.3816756 4.2560306 0.4210263These are different, once again because of the different normalization, from what is reported in equation (38) on page 57 in Ochoa (1984). We can redo this as we did for the direct prices.
# vector of market prices
mktp <- c(4,60,7)
# renormalize price of production vector
si2$pp <- si2$pp*(sum(mktp*as.vector(Q))/sum(as.vector(Q)))
# see vector of prices of production
(si2$pp)
#> [1] 5.515875 61.507034 6.084562Now we have the vector of direct prices that is very close (though not exactly equal) to what is reported in equation (38) on page 57 in Ochoa (1984). These small differences arise, most probably, from numerical issues. In any case, the differences are small enough to be ignored.
We continue working with the 3-industry example and implement the New Interpretation of Marx’s labor theory of value. Please note that Ochoa (1984) did not implement the NI. We are doing this solely to compare the results between the SI and the NI for his example.
ni2 <- ppnewint2(
A = A,
l = l,
v = v,
w = wavg,
Q = Q,
D = D,
K = K,
t = t,
Tax = Tax
)What is the uniform rate of profit?
ni2$urop
#> [1] 0.1569311What is the vector of labor values?
ni2$lvalues
#> [,1] [,2] [,3]
#> [1,] 0.5192079 8.309406 0.9407729What is the vector of direct prices (using the same normalization as for the SI above)?
# vector of market prices
mktp <- c(4,60,7)
# normalization factor: kappa
mykappa <- sum(mktp*as.vector(Q))/sum(as.vector(ni2$lvalues)*as.vector(Q))
# renormalize direct prices
ni2$dp <- mykappa * ni2$lvalues
# see new vector of direct prices
(ni2$dp)
#> [,1] [,2] [,3]
#> [1,] 3.797694 60.77831 6.881188What is the vector of prices of production (once again using the same normalization as in the SI)?
# vector of market prices
mktp <- c(4,60,7)
# renormalize price of production vector
ni2$pp <- ni2$pp*(sum(mktp*as.vector(Q))/sum(as.vector(Q)))
# see vector of prices of production
(ni2$pp)
#> [,1] [,2] [,3]
#> [1,] 56.42547 698.3152 72.50102Let us compare the results from the SI and NI for direct price vectors
# bring together results on direct prices
myresults <- as.data.frame(
cbind(as.vector(si2$dp),as.vector(ni2$dp))
)
rownames(myresults) <- c("Ind1","Ind2","Ind3")
colnames(myresults) <- c("SI", "NI")
# see comparison
(myresults)
#> SI NI
#> Ind1 3.797694 3.797694
#> Ind2 60.778306 60.778306
#> Ind3 6.881188 6.881188and for market prices
# bring together results on direct prices
myresults <- as.data.frame(
cbind(as.vector(si2$pp),as.vector(ni2$pp))
)
rownames(myresults) <- c("Ind1","Ind2","Ind3")
colnames(myresults) <- c("SI", "NI")
# see comparison
(myresults)
#> SI NI
#> Ind1 5.515875 56.42547
#> Ind2 61.507034 698.31516
#> Ind3 6.084562 72.50102Basu, D. The Logic of Capital: An Introduction to Marxist Economic Theory. 2021. Cambridge University Press. Available here: https://doi.org/10.1017/9781108937559
Moraitis, T. and Basu, D. “Alternative Approaches to Labor Values and Prices of Production: Theory and Evidence.” Structural Change and Economic Dynamics, 2026. Available here: https://doi.org/10.1016/j.strueco.2026.03.009