| Title: | Agricultural Export Competitiveness and Risk Analysis |
|---|---|
| Description: | An integrated and reproducible workflow for analysing the competitiveness and risk of agricultural and horticultural exports. It measures destination and product concentration (Herfindahl-Hirschman, entropy and equivalent-number indices), revealed comparative advantage (Balassa, 1965) <doi:10.1111/j.1467-9957.1965.tb00050.x> and its symmetric form, relative unit values, and constant market share decomposition of export growth. It tests vertical price transmission between export and domestic prices with Engle-Granger cointegration (Engle and Granger, 1987) <doi:10.2307/1913236> using MacKinnon (2010) critical values and symmetric or asymmetric error correction models. It quantifies exchange-rate exposure of a multi-currency export portfolio (volatility, diversification ratio, risk contributions and value at risk), screens destination markets with composite entry-risk scores, and identifies risk-efficient destination mixes by mean-variance portfolio optimisation (Markowitz, 1952) <doi:10.2307/2975974>. Simulated example data for Indian mango, grape, pomegranate and processed horticultural exports illustrate the workflow. |
| Authors: | Anbukkani Perumal [aut, cre, cph] |
| Maintainer: | Anbukkani Perumal <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.1.0 |
| Built: | 2026-10-24 14:47:15 UTC |
| Source: | https://github.com/cran/agriTradeRisk |
Decomposes the change in a country's exports between two periods into four effects (Leamer and Stern, 1970; Ahmadi-Esfahani, 2006):
exports would have grown at the rate of
world imports covered by the data;
gain from specialising in products whose world demand grew faster than average;
gain from exporting each product to markets where its demand grew faster;
the residual, the change in market shares.
, and are growth rates of world imports of
product in market , of product in all markets, and
of all products in all markets in the data.
cms_decomposition(data, product, market, export0, export1, world0, world1)cms_decomposition(data, product, market, export0, export1, world0, world1)
data |
A data frame with one row per product-market pair. |
product, market
|
Names of product and market columns. |
export0, export1
|
Columns with the country's exports in the base and end periods. |
world0, world1
|
Columns with world imports of the product by the market in the base and end periods (must be positive). |
A list of class 'cms_decomposition' with 'effects' (data frame of the four effects, their total and their shares of the export change), 'by_product' (effects by product) and 'growth' (world growth rates).
Leamer, E. E. and Stern, R. M. (1970). *Quantitative International Economics*. Allyn and Bacon, Boston.
Ahmadi-Esfahani, F. Z. (2006). Constant market shares analysis: uses, limitations and prospects. *Australian Journal of Agricultural and Resource Economics*, 50(4), 510-526.
d0 <- subset(hort_exports, year == 2015) d1 <- subset(hort_exports, year == 2023) cms <- merge(d0, d1, by = c("product", "destination"), suffixes = c("0", "1")) cms_decomposition(cms, "product", "destination", "export_value0", "export_value1", "world_import0", "world_import1")d0 <- subset(hort_exports, year == 2015) d1 <- subset(hort_exports, year == 2023) cms <- merge(d0, d1, by = c("product", "destination"), suffixes = c("0", "1")) cms_decomposition(cms, "product", "destination", "export_value0", "export_value1", "world_import0", "world_import1")
Computes standard competitiveness indicators for a country's exports of
product :
Balassa revealed comparative advantage
, where and are the
country's exports of the product and of all goods, and and
the corresponding world exports. Values above 1 indicate a
revealed comparative advantage.
Revealed symmetric comparative advantage
, bounded between -1 and 1.
World market share .
If quantities are supplied, the export unit value, the world unit value and their ratio, a price-based competitiveness (or quality) indicator.
competitiveness_index( data, export, total_export, world_export, world_total, quantity = NULL, world_quantity = NULL )competitiveness_index( data, export, total_export, world_export, world_total, quantity = NULL, world_quantity = NULL )
data |
A data frame, one row per product (and year). |
export |
Column with the country's exports of the product. |
total_export |
Column with the country's total exports. |
world_export |
Column with world exports of the product. |
world_total |
Column with world total exports. |
quantity, world_quantity
|
Optional columns with the country's and the world's export quantities of the product. |
'data' with added columns 'rca', 'rsca', 'world_share' and, when quantities are given, 'unit_value', 'world_unit_value' and 'unit_value_ratio'. The result has class 'competitiveness_index'.
Balassa, B. (1965). Trade liberalisation and "revealed" comparative advantage. *The Manchester School*, 33(2), 99-123. doi:10.1111/j.1467-9957.1965.tb00050.x
prod_year <- aggregate(cbind(export_value, world_import) ~ product + year, data = hort_exports, FUN = sum) dat <- merge(prod_year, trade_totals, by = "year") ci <- competitiveness_index(dat, "export_value", "india_total_exports", "world_import", "world_total_exports") head(ci[, c("product", "year", "rca", "rsca", "world_share")])prod_year <- aggregate(cbind(export_value, world_import) ~ product + year, data = hort_exports, FUN = sum) dat <- merge(prod_year, trade_totals, by = "year") ci <- competitiveness_index(dat, "export_value", "india_total_exports", "world_import", "world_total_exports") head(ci[, c("product", "year", "rca", "rsca", "world_share")])
Treats export earnings invoiced in several currencies as a currency portfolio. Using log changes of exchange rates (home currency per unit of foreign currency) and the share of export value earned in each currency, it computes:
annualised volatility of each currency and their correlations;
a trade-weighted (geometric) effective exchange-rate index;
portfolio volatility and the
undiversified volatility ; their ratio is
the diversification ratio (values above 1 indicate risk reduction
from currency diversification);
each currency's percentage contribution to portfolio variance,
;
parametric and historical value at risk of export earnings in home currency over 'horizon' periods at confidence level 'conf'.
If an export series is supplied, the exposure elasticity is estimated by regressing its log change on the log change of the effective exchange rate.
exchange_rate_exposure( rates, shares, export_value = 1, freq = 12, horizon = 1, conf = 0.95, exports = NULL )exchange_rate_exposure( rates, shares, export_value = 1, freq = 12, horizon = 1, conf = 0.95, exports = NULL )
rates |
A data frame or matrix of exchange rates, one column per currency (home currency per unit of foreign currency), one row per period, in time order. |
shares |
Named numeric vector of export shares by currency; names must match columns of 'rates'. Normalised to sum to 1. |
export_value |
Export value (home currency) exposed over the horizon, used for value at risk. |
freq |
Periods per year (12 for monthly data) for annualisation. |
horizon |
Value-at-risk horizon in periods. |
conf |
Confidence level for value at risk. |
exports |
Optional numeric series of export values or prices (same length as 'rates') for estimating the exposure elasticity. |
A list of class 'exchange_rate_exposure' with 'currencies' (share, annualised volatility and risk contribution per currency), 'correlation', 'portfolio' (annualised portfolio and undiversified volatility, diversification ratio, parametric and historical value at risk), 'effective_index' (trade-weighted index, first period = 100) and, if 'exports' is supplied, 'elasticity' (estimate, standard error, p-value).
sh <- c(USD = 0.35, EUR = 0.20, GBP = 0.15, AED = 0.20, BDT = 0.10) ex <- exchange_rate_exposure(fx_rates[, names(sh)], sh, export_value = 1e9, freq = 12) exsh <- c(USD = 0.35, EUR = 0.20, GBP = 0.15, AED = 0.20, BDT = 0.10) ex <- exchange_rate_exposure(fx_rates[, names(sh)], sh, export_value = 1e9, freq = 12) ex
Measures how concentrated exports are across destinations (or across
products, by passing the product column as 'partner'). For partner
shares the function reports the Herfindahl-Hirschman index
, its normalised form
, the equivalent number of equally sized
partners , the combined share of the 'top' largest partners,
and Theil's entropy with its normalised form
(divided by ). Higher HHI and lower entropy indicate greater
concentration and therefore greater exposure to shocks in individual
markets.
export_concentration(data, value, partner, by = NULL, top = 3)export_concentration(data, value, partner, by = NULL, top = 3)
data |
A data frame with one row per partner (and group). |
value |
Name of the column holding export values (non-negative). |
partner |
Name of the column identifying destinations (or products). |
by |
Optional names of grouping columns, for example product and year. |
top |
Number of leading partners for the top-share measure. |
A data frame of class 'export_concentration' with one row per group and columns 'total', 'n_partners', 'hhi', 'hhi_normalised', 'equivalent_partners', 'top_share', 'entropy', 'entropy_normalised', 'leading_partner' and 'leading_share'.
ec <- export_concentration(hort_exports, value = "export_value", partner = "destination", by = c("product", "year")) head(ec)ec <- export_concentration(hort_exports, value = "export_value", partner = "destination", by = c("product", "year")) head(ec)
Synthetic monthly exchange rates (Indian rupees per unit of foreign currency), January 2014 to December 2023. AED and SAR follow their US dollar pegs. Not official statistics.
fx_ratesfx_rates
A data frame with 120 rows and 8 columns: 'date', 'USD', 'EUR', 'GBP', 'AED', 'SAR', 'BDT' and 'RUB'.
Simulated.
Synthetic monthly export unit values and domestic wholesale prices of grapes (INR per kg), January 2012 to December 2023, generated as a cointegrated pair with faster adjustment when domestic prices are above their long-run relationship. Not official statistics.
grape_pricesgrape_prices
A data frame with 144 rows and 3 columns: 'date', 'export_unit_value' and 'domestic_price'.
Simulated.
Simulated annual exports of four Indian horticultural product groups to eight destination markets, with world imports of each product by each destination. The data are **synthetic**, generated by 'data-raw/make_data.R' for illustration; they are not official trade statistics.
hort_exportshort_exports
A data frame with 448 rows and 6 columns:
Year, 2010-2023.
'"mango"', '"grapes"', '"pomegranate"' or '"processed"' (processed fruit and vegetable products).
Destination market.
Exports from India, USD million.
Export quantity, tonnes.
World imports of the product by the destination, USD million.
Simulated.
Applies mean-variance portfolio analysis (Markowitz, 1952) to the
allocation of exports across destination markets. Each market is an
"asset" whose return is a performance measure such as the growth of
export earnings or the realised export price (unit value) change. The
function finds destination shares that minimise
subject to and
, where share bounds reflect market-access or
capacity limits. It reports the minimum-variance mix, the mix with the
highest return per unit of risk on the efficient frontier, the current
mix and the efficient frontier, so that the risk reduction available
from diversification can be compared with the current market structure.
market_diversification( returns = NULL, shares = NULL, mean = NULL, cov = NULL, min_share = 0, max_share = 1, n_frontier = 25 )market_diversification( returns = NULL, shares = NULL, mean = NULL, cov = NULL, min_share = 0, max_share = 1, n_frontier = 25 )
returns |
A data frame or matrix of returns, one column per market and one row per period. Alternatively supply 'mean' and 'cov'. |
shares |
Optional named vector of current destination shares. |
mean, cov
|
Optional mean vector and covariance matrix of returns, used instead of 'returns'. |
min_share, max_share
|
Lower and upper bounds on each market's share (scalars or one per market). |
n_frontier |
Number of points on the efficient frontier. |
The problem is solved by projected gradient descent on the bounded simplex, which needs no additional packages.
A list of class 'market_diversification' with 'weights' (data frame of current, minimum-variance and best return-to-risk shares by market), 'summary' (expected return, risk, return-to-risk ratio and Herfindahl index of each mix), 'frontier' (data frame of efficient portfolios) and the inputs 'mean' and 'cov'. A 'plot()' method draws the frontier.
Markowitz, H. (1952). Portfolio selection. *The Journal of Finance*, 7(1), 77-91. doi:10.2307/2975974
grapes <- subset(hort_exports, product == "grapes") wide <- reshape(grapes[, c("year", "destination", "export_value")], idvar = "year", timevar = "destination", direction = "wide") vals <- as.matrix(wide[order(wide$year), -1]) colnames(vals) <- sub("export_value.", "", colnames(vals)) growth <- diff(log(vals)) cur <- vals[nrow(vals), ] / sum(vals[nrow(vals), ]) md <- market_diversification(growth, shares = cur, max_share = 0.4) md plot(md)grapes <- subset(hort_exports, product == "grapes") wide <- reshape(grapes[, c("year", "destination", "export_value")], idvar = "year", timevar = "destination", direction = "wide") vals <- as.matrix(wide[order(wide$year), -1]) colnames(vals) <- sub("export_value.", "", colnames(vals)) growth <- diff(log(vals)) cur <- vals[nrow(vals), ] / sum(vals[nrow(vals), ]) md <- market_diversification(growth, shares = cur, max_share = 0.4) md plot(md)
Combines indicators of the risk of entering or expanding in destination
markets, for example sanitary and phytosanitary rejection rates, tariff
rates, non-tariff measure counts, price volatility, exchange-rate
volatility, distance or transit time, and competitor market share, into
a single score. Each indicator is rescaled to 0-1 by min-max
normalisation and oriented so that 1 is the riskiest value; the score is
the weighted mean of the rescaled indicators. Optionally, a market
attractiveness indicator (such as import demand growth) is combined with
the score into a risk-adjusted attractiveness index
, where is rescaled attractiveness and
the risk aversion.
market_entry_risk( data, market, indicators, higher_is_riskier, weights = NULL, attractiveness = NULL, risk_aversion = 0.5 )market_entry_risk( data, market, indicators, higher_is_riskier, weights = NULL, attractiveness = NULL, risk_aversion = 0.5 )
data |
A data frame with one row per market. |
market |
Name of the market column. |
indicators |
Names of indicator columns. |
higher_is_riskier |
Logical vector, one per indicator: 'TRUE' if a higher value means more risk. |
weights |
Optional non-negative weights, one per indicator (normalised to sum to 1). Equal weights by default. |
attractiveness |
Optional name of a column measuring market attractiveness (higher is better). |
risk_aversion |
Weight |
A data frame of class 'market_entry_risk' with the market, the rescaled indicators, 'risk_score', 'risk_rank' (1 = least risky) and, if 'attractiveness' is given, 'attractiveness_scaled', 'risk_adjusted_attractiveness' and 'priority_rank'.
mk <- data.frame(market = c("UAE", "UK", "Netherlands", "USA", "Bangladesh"), sps_rejections = c(2, 5, 8, 6, 1), tariff = c(0, 0, 0, 2, 10), price_cv = c(0.15, 0.10, 0.12, 0.18, 0.25), demand_growth = c(0.06, 0.03, 0.04, 0.05, 0.08)) market_entry_risk(mk, "market", c("sps_rejections", "tariff", "price_cv"), higher_is_riskier = c(TRUE, TRUE, TRUE), attractiveness = "demand_growth")mk <- data.frame(market = c("UAE", "UK", "Netherlands", "USA", "Bangladesh"), sps_rejections = c(2, 5, 8, 6, 1), tariff = c(0, 0, 0, 2, 10), price_cv = c(0.15, 0.10, 0.12, 0.18, 0.25), demand_growth = c(0.06, 0.03, 0.04, 0.05, 0.08)) market_entry_risk(mk, "market", c("sps_rejections", "tariff", "price_cv"), higher_is_riskier = c(TRUE, TRUE, TRUE), attractiveness = "demand_growth")
Plot the efficient frontier of destination markets
## S3 method for class 'market_diversification' plot(x, ...)## S3 method for class 'market_diversification' plot(x, ...)
x |
A [market_diversification()] object. |
... |
Further arguments passed to [graphics::plot()]. |
'x', invisibly.
set.seed(1) r <- matrix(rnorm(60, 0.05, 0.1), 20, 3, dimnames = list(NULL, c("A", "B", "C"))) plot(market_diversification(r))set.seed(1) r <- matrix(rnorm(60, 0.05, 0.1), 20, 3, dimnames = list(NULL, c("A", "B", "C"))) plot(market_diversification(r))
Tests whether domestic prices (for example wholesale or farm-gate prices) move with export prices (or export unit values) in the long run and how quickly deviations are corrected.
price_transmission( domestic, world, log = TRUE, ecm_lags = 1, max_lag = 4, asymmetric = FALSE )price_transmission( domestic, world, log = TRUE, ecm_lags = 1, max_lag = 4, asymmetric = FALSE )
domestic |
Numeric vector or time series of domestic prices. |
world |
Numeric vector or time series of export or world prices, same length as 'domestic'. |
log |
Logical; take natural logarithms of prices first. |
ecm_lags |
Number of lagged differences |
max_lag |
Maximum lag order considered in the residual ADF test. |
asymmetric |
Logical; estimate an asymmetric error correction model. |
**Step 1: long-run relationship.** , where
is the long-run price transmission elasticity when prices are in
logs.
**Step 2: Engle-Granger cointegration test.** An augmented Dickey-Fuller
regression without deterministic terms is fitted to the residuals
, with the lag order chosen by AIC up to 'max_lag'. The t
statistic is compared with the asymptotic critical values of MacKinnon
(2010) for two variables with a constant: -3.896 (1
-3.044 (10
**Step 3: error correction model.**
is the short-run elasticity and (expected to be
negative) the speed of adjustment; the half-life of a deviation is
periods. With 'asymmetric = TRUE' the
error correction term is split into positive and negative parts
(Granger and Lee, 1989), and an F test of equal adjustment speeds is
reported.
A list of class 'price_transmission' with 'long_run' (intercept, elasticity, R-squared), 'cointegration' (ADF statistic, lag, critical values and decision at 5 percent), 'ecm' (coefficient table of the error correction model), 'adjustment' (speed of adjustment and half-life; separate values for positive and negative deviations when asymmetric, with the F test), and the fitted 'lm' models.
Engle, R. F. and Granger, C. W. J. (1987). Co-integration and error correction: representation, estimation, and testing. *Econometrica*, 55(2), 251-276. doi:10.2307/1913236
Granger, C. W. J. and Lee, T. H. (1989). Investigation of production, sales and inventory relationships using multicointegration and non-symmetric error correction models. *Journal of Applied Econometrics*, 4(S1), S145-S159. doi:10.1002/jae.3950040508
MacKinnon, J. G. (2010). Critical values for cointegration tests. Queen's Economics Department Working Paper No. 1227, Queen's University, Kingston, Ontario.
pt <- price_transmission(grape_prices$domestic_price, grape_prices$export_unit_value) pt price_transmission(grape_prices$domestic_price, grape_prices$export_unit_value, asymmetric = TRUE)$adjustmentpt <- price_transmission(grape_prices$domestic_price, grape_prices$export_unit_value) pt price_transmission(grape_prices$domestic_price, grape_prices$export_unit_value, asymmetric = TRUE)$adjustment
Synthetic annual totals used with [hort_exports] to compute revealed comparative advantage. Not official statistics.
trade_totalstrade_totals
A data frame with 14 rows and 3 columns: 'year', 'india_total_exports' and 'world_total_exports' (USD million).
Simulated.