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.3709973
Here 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.392127
Thus, 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] 1
Yes, 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.557706
Here 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.1121543
In 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.02586745
From 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.05632964
From 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.2337492
This 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.9407729
This 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.4761495
These 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.881188
Now 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.4210263
These 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.084562
Now 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.1569311
What is the vector of labor values?
ni2$lvalues
#> [,1] [,2] [,3]
#> [1,] 0.5192079 8.309406 0.9407729
What 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.881188
What 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.50102
Let 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.881188
and 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.50102
Basu, 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
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.