VXX ETN: wetin e be and why e dey bleed
VXX no be the VIX. Na ETN wey dey roll VIX futures every day, and the panels here show how e dey grind down if you hold am, plus the 2020 spike wey e give back.
VXX no be the VIX. VXX na one ETN, exchange traded note, wey dey hold the two nearest VIX futures months and dey roll dem every single trading day, so wetin e dey follow na VIX futures, no be the spot number wey dem dey shout for TV. If you buy VXX for your Bamboo, Trove, Chaka or Risevest app the day market scatter, wetin enter your account na short dated futures exposure wrapped inside one IOU from a bank. The panels below show, with real daily prices, wetin dey happen to that kind hold over months and years.
Wetin VXX actually hold
Separate two things first.
- The VIX na index wey CBOE dey calculate from SPX option prices. Nobody fit buy the index itself. Na number, like temperature reading. We break the calculation down for wetin be the VIX index.
- VIX futures na contract wey settle to that index on one fixed future date. VXX dey hold the front month and the second month, and every day e dey shift small piece of the position from the front to the back, to keep the average maturity near 30 days.
That daily shift na the engine of this whole post. Whenever the second month dey price higher than the front month, the daily roll dey sell the cheaper contract and buy the costlier one. Market people call that shape contango, and the drag wey e leave behind na roll yield. We do the full mechanics for contango and roll yield inside ETF. VXX no promise anybody the VIX level. Wetin the note promise na the return of one futures index after that daily roll, minus fees.
Wetin the long hold look like
No adjective, just the tape. This panel take the month end close for VXX from January 2019, adjusted for the reverse splits wey we go show below.
| month | month_label | vxx_close_adj | change_pct |
|---|---|---|---|
| 2019-01-01 | Jan 2019 | 158474.24 | 0 |
| 2019-05-01 | May 2019 | 124600.32 | -21.4 |
| 2019-06-01 | Jun 2019 | 106496 | -32.8 |
| 2019-07-01 | Jul 2019 | 96624.64 | -39 |
| 2019-08-01 | Aug 2019 | 110592 | -30.2 |
| 2019-09-01 | Sep 2019 | 97239.04 | -38.6 |
| 2019-10-01 | Oct 2019 | 80896 | -49 |
| 2019-11-01 | Nov 2019 | 67747.84 | -57.2 |
| 2019-12-01 | Dec 2019 | 61931.52 | -60.9 |
| 2020-01-01 | Jan 2020 | 66355.2 | -58.1 |
| 2020-02-01 | Feb 2020 | 93429.76 | -41 |
| 2020-03-01 | Mar 2020 | 189440 | 19.5 |
| 2020-04-01 | Apr 2020 | 155115.52 | -2.1 |
| 2020-05-01 | May 2020 | 135700.48 | -14.4 |
| 2020-06-01 | Jun 2020 | 139059.2 | -12.3 |
| 2020-07-01 | Jul 2020 | 116817.92 | -26.3 |
| 2020-08-01 | Aug 2020 | 109977.6 | -30.6 |
| 2020-09-01 | Sep 2020 | 101990.4 | -35.6 |
| 2020-10-01 | Oct 2020 | 108666.88 | -31.4 |
| 2020-11-01 | Nov 2020 | 70369.28 | -55.6 |
The exact SQL behind every number
WITH splits AS
(
SELECT
groupArray(execution_date) AS split_dates,
groupArray(price_factor) AS price_factors
FROM
(
SELECT
execution_date,
toFloat64(any(split_from)) / toFloat64(any(split_to)) AS price_factor
FROM global_markets.stocks_splits
WHERE ticker = 'VXX'
GROUP BY execution_date
)
),
daily AS
(
SELECT
a.date AS date,
toFloat64(a.close) * arrayProduct(arrayMap((d, f) -> if(d > a.date, f, 1.0), s.split_dates, s.price_factors)) AS adj_close
FROM global_markets.stocks_daily_aggs AS a
CROSS JOIN splits AS s
WHERE a.ticker = 'VXX'
AND a.date >= toDate('2019-01-01')
),
month_end AS
(
SELECT
toStartOfMonth(date) AS month_start,
argMax(adj_close, date) AS adj_close
FROM daily
GROUP BY month_start
)
SELECT
toString(month_start) AS month,
formatDateTime(month_start, '%b %Y') AS month_label,
round(adj_close, 2) AS vxx_close_adj,
round(100 * (adj_close / first_value(adj_close) OVER (ORDER BY month_start) - 1), 1) AS change_pct
FROM month_end
ORDER BY month_startThe panel run from Jan 2019 to Sep 2026, 90 month end prices. Over that stretch the split adjusted price move from $158474.24 to $17.51, wey be -100% end to end.
Two things dey inside those numbers. One, the January 2019 figure dey enter six figures as plain arithmetic: a stack of 1-for-4 reverse splits sit after that month, and each one multiply the older quote by four to state am in today's share terms. Na the same slice of the note, just written the way one share dey quote today. Two, the end to end column dey talk about that adjusted stake, no be about the trading quote. Na near total wipeout in adjusted terms, while the reverse splits keep the live quote, the last number inside the panel, inside normal trading range. The note no reach zero; the adjusted value na the thing wey collapse.
Look the shape well, e no be straight line down. The line dey flat, den e dey shoot up for a few weeks when volatility waka, den the grind dey continue from the new level. Anybody wey enter during one of those jumps and hold am dey carry the grind wey follow.
Year by year, how the grind look
Same series, cut by calendar year: first session close of the year against the last one.
| year | change_pct | sessions |
|---|---|---|
| 2019 | -66.8 | 188 |
| 2020 | 15.7 | 253 |
| 2021 | -93.7 | 252 |
| 2022 | -21.1 | 251 |
| 2023 | -93.1 | 250 |
| 2024 | -81.6 | 252 |
| 2025 | -43.5 | 250 |
| 2026 | -32.9 | 181 |
The exact SQL behind every number
WITH splits AS
(
SELECT
groupArray(execution_date) AS split_dates,
groupArray(price_factor) AS price_factors
FROM
(
SELECT
execution_date,
toFloat64(any(split_from)) / toFloat64(any(split_to)) AS price_factor
FROM global_markets.stocks_splits
WHERE ticker = 'VXX'
GROUP BY execution_date
)
),
daily AS
(
SELECT
a.date AS date,
toFloat64(a.close) * arrayProduct(arrayMap((d, f) -> if(d > a.date, f, 1.0), s.split_dates, s.price_factors)) AS adj_close
FROM global_markets.stocks_daily_aggs AS a
CROSS JOIN splits AS s
WHERE a.ticker = 'VXX'
AND a.date >= toDate('2019-01-01')
)
SELECT
toString(toYear(date)) AS year,
round(100 * (argMax(adj_close, date) / argMin(adj_close, date) - 1), 1) AS change_pct,
count() AS sessions
FROM daily
GROUP BY year
ORDER BY year2019 close at -66.8%. Even 2020, the year of the biggest volatility wahala since 2008, land at 15.7% on this measure, after the March run wey we trace below. The last row na 2026 with 181 sessions inside am, so e still dey partial, and e dey stand at -32.9%.
The reverse splits na the receipt
When a price grind down reach one point, the quote go too small to trade well. The fix wey issuers dey use na reverse split: four shares turn one share, and the quoted price multiply by four. VXX don do am more than once.
| execution_date | split_label | old_shares_per_share_now |
|---|---|---|
| 2010-11-09 | 1-for-4 | 4 |
| 2012-10-05 | 1-for-4 | 16 |
| 2013-11-08 | 1-for-4 | 64 |
| 2016-08-09 | 1-for-4 | 256 |
| 2017-08-23 | 1-for-4 | 1024 |
| 2021-04-23 | 1-for-4 | 4096 |
| 2023-03-07 | 1-for-4 | 16384 |
| 2024-07-24 | 1-for-4 | 65536 |
The exact SQL behind every number
SELECT
toString(execution_date) AS execution_date,
concat(toString(split_to), '-for-', toString(split_from)) AS split_label,
round(exp(sum(log(toFloat64(split_from) / toFloat64(split_to))) OVER (ORDER BY execution_date)), 0) AS old_shares_per_share_now
FROM
(
SELECT
execution_date,
any(split_from) AS split_from,
any(split_to) AS split_to
FROM global_markets.stocks_splits
WHERE ticker = 'VXX'
GROUP BY execution_date
)
ORDER BY execution_date8 splits dey inside the record, and the latest one na 1-for-4 on 2024-07-24. The last column dey count how many old shares equal one share of today: by the final row e reach 65536. Any price chart wey no adjust for these events go show you a note wey look like e hold value, when wetin actually happen na that the share count keep shrinking.
The 2020 window: e jump, e give am back
Now pin one real window wey no dey change again. Weekly closes from the week volatility begin waka for February 2020, running one full year forward. gain_pct na where the hold dey each week compared with the first week. peak_gain_pct na the best point the hold ever touch up till that week.
| week | week_label | gain_pct | peak_gain_pct |
|---|---|---|---|
| 2020-02-10 | Feb 10, 2020 | 0 | 0 |
| 2020-02-17 | Feb 17, 2020 | 10.2 | 10.2 |
| 2020-02-24 | Feb 24, 2020 | 68.7 | 68.7 |
| 2020-03-02 | Mar 2, 2020 | 120.6 | 120.6 |
| 2020-03-09 | Mar 9, 2020 | 219.5 | 250.3 |
| 2020-03-16 | Mar 16, 2020 | 347.9 | 410.4 |
| 2020-03-23 | Mar 23, 2020 | 274.3 | 410.4 |
| 2020-03-30 | Mar 30, 2020 | 236.2 | 410.4 |
| 2020-04-06 | Apr 6, 2020 | 207.5 | 410.4 |
| 2020-04-13 | Apr 13, 2020 | 188.8 | 410.4 |
| 2020-04-20 | Apr 20, 2020 | 207.1 | 410.4 |
| 2020-04-27 | Apr 27, 2020 | 204.7 | 410.4 |
| 2020-05-04 | May 4, 2020 | 158.5 | 410.4 |
| 2020-05-11 | May 11, 2020 | 170.7 | 410.4 |
| 2020-05-18 | May 18, 2020 | 154.1 | 410.4 |
| 2020-05-25 | May 25, 2020 | 145 | 410.4 |
| 2020-06-01 | Jun 1, 2020 | 115.8 | 410.4 |
| 2020-06-08 | Jun 8, 2020 | 186.3 | 410.4 |
| 2020-06-15 | Jun 15, 2020 | 172.9 | 410.4 |
| 2020-06-22 | Jun 22, 2020 | 177.4 | 410.4 |
The exact SQL behind every number
WITH splits AS
(
SELECT
groupArray(execution_date) AS split_dates,
groupArray(price_factor) AS price_factors
FROM
(
SELECT
execution_date,
toFloat64(any(split_from)) / toFloat64(any(split_to)) AS price_factor
FROM global_markets.stocks_splits
WHERE ticker = 'VXX'
GROUP BY execution_date
)
),
daily AS
(
SELECT
a.date AS date,
toFloat64(a.close) * arrayProduct(arrayMap((d, f) -> if(d > a.date, f, 1.0), s.split_dates, s.price_factors)) AS adj_close
FROM global_markets.stocks_daily_aggs AS a
CROSS JOIN splits AS s
WHERE a.ticker = 'VXX'
AND a.date >= toDate('2020-02-14')
AND a.date < toDate('2021-03-01')
),
weekly AS
(
SELECT
toMonday(date) AS week_start,
argMax(adj_close, date) AS week_close,
max(adj_close) AS week_high
FROM daily
GROUP BY week_start
)
SELECT
toString(week_start) AS week,
formatDateTime(week_start, '%b %e, %Y') AS week_label,
round(100 * (week_close / first_value(week_close) OVER (ORDER BY week_start) - 1), 1) AS gain_pct,
round(100 * (max(week_high) OVER (ORDER BY week_start) / first_value(week_close) OVER (ORDER BY week_start) - 1), 1) AS peak_gain_pct
FROM weekly
ORDER BY week_startStarting from the week of Feb 10, 2020, the running peak reach 410.4% above where the hold begin. Na plenty money for a few weeks, and na why VXX dey trend for every market wahala. Then follow the same line go the end: by Feb 22, 2021, about one year later, the same hold dey stand at 18.6% from the start point. That na the part wey people dey miss. The jump and the giveback dey live inside the same instrument.
The volatility level dey come back. The note no dey come back.
Volatility itself no dey trend to zero. E dey climb, e dey fall back to a normal zone. To show that with per contract data, this panel take SPY options near the money with 20 to 45 days to expiry and read the median implied volatility for each month. Implied volatility na the volatility number wey the option price dey imply, the same family of number wey the VIX dey summarise for SPX.
| month | month_label | spy_iv_pct | window_high_pct |
|---|---|---|---|
| 2021-09-01 | Sep 2021 | 14.7 | 27.9 |
| 2021-10-01 | Oct 2021 | 14.3 | 27.9 |
| 2021-11-01 | Nov 2021 | 14 | 27.9 |
| 2021-12-01 | Dec 2021 | 16.1 | 27.9 |
| 2022-01-01 | Jan 2022 | 18.4 | 27.9 |
| 2022-02-01 | Feb 2022 | 21.6 | 27.9 |
| 2022-03-01 | Mar 2022 | 22.1 | 27.9 |
| 2022-04-01 | Apr 2022 | 19.5 | 27.9 |
| 2022-05-01 | May 2022 | 26.3 | 27.9 |
| 2022-06-01 | Jun 2022 | 25 | 27.9 |
| 2022-07-01 | Jul 2022 | 23 | 27.9 |
| 2022-08-01 | Aug 2022 | 19.8 | 27.9 |
| 2022-09-01 | Sep 2022 | 25.6 | 27.9 |
| 2022-10-01 | Oct 2022 | 27.9 | 27.9 |
| 2022-11-01 | Nov 2022 | 23 | 27.9 |
| 2022-12-01 | Dec 2022 | 20.8 | 27.9 |
| 2023-01-01 | Jan 2023 | 19.3 | 27.9 |
| 2023-02-01 | Feb 2023 | 18.7 | 27.9 |
| 2023-03-01 | Mar 2023 | 19.9 | 27.9 |
| 2023-04-01 | Apr 2023 | 16.4 | 27.9 |
The exact SQL behind every number
SELECT
month,
month_label,
spy_iv_pct,
round(max(spy_iv_pct) OVER (), 1) AS window_high_pct
FROM
(
SELECT
toStartOfMonth(date) AS month_start,
toString(toStartOfMonth(date)) AS month,
formatDateTime(toStartOfMonth(date), '%b %Y') AS month_label,
round(100 * quantileDeterministic(0.5)(toFloat64(implied_volatility), cityHash64(ticker)), 1) AS spy_iv_pct
FROM global_markets.options_greeks
WHERE underlying_symbol = 'SPY'
AND iv_converged = 1
AND volume > 0
AND days_to_expiry BETWEEN 20 AND 45
AND toFloat64(underlying_close) > 0
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05
AND date >= toDate('2021-09-01')
GROUP BY month_start, month, month_label
)
ORDER BY month_startFrom Sep 2021 the monthly median sit at 14.7%, the highest month inside the window print 27.9%, and by Sep 2026 e dey 13.3%. Na round trip. Put the two panels side by side and the lesson clear: the volatility level come back to im zone, the VXX price no come back. The gap between the two na the roll plus fees, stacking session after session. Na also why VIX linked products no dey move one to one with the index, something we treat on im own for why VIX options no dey track the VIX.
ETN mean say na the issuer you dey trust
One more part wey investors dey skip when dem compare VXX with a normal ETF. An ETF dey hold assets: shares, futures, cash, inside a fund wey get custodian. An ETN na unsecured debt note. Barclays Bank PLC issue VXX, and wetin you hold na dem promise to pay the index return. Four practical points follow from that structure.
- Credit risk: na the issuer promise you carry. No basket of VIX futures dey sit somewhere with your name on am.
- Issuance risk: an issuer fit stop creating new units. When creation stop, the market price fit waka far from the note indicative value, and whoever buy for that premium carry the gap.
- Call and maturity: ETNs get maturity date, and plenty of dem give the issuer right to call the note early. Those terms dey inside the prospectus, no be inside the app wey you dey use to buy.
- Settlement by formula: when a note end, na the terms of the note decide wetin you collect, no be the sale of any pot of assets.
Daily arithmetic wey work the same kind way dey inside leverage products too, and we cover am for how leveraged ETF dey work.
So who dey use VXX, and how?
Wetin the panels dey show na that VXX na short horizon instrument by design. Traders wey use am dey hold am for days or weeks around one event dem dey watch, den dem exit. The daily roll na cost wey dey run every session, so the longer the hold, the more of that cost the position dey carry. Nothing here na recommendation to buy or sell anything. Na the mechanics and the measured history. One last basic point for anybody buying through a Nigerian app: VXX no dey pay dividend or coupon. All the return na price.
FAQ
VXX and VIX na the same thing?
No. The VIX na index wey CBOE calculate from SPX option prices, and nobody fit buy the index directly. VXX na ETN wey hold the first two VIX futures months and roll dem daily, so the two numbers fit waka different on the same day.
Why VXX price dey grind down over time?
The note dey roll from the front VIX futures month into the next month every trading day. When the next month dey cost more, that shape wey dem call contango, the daily roll dey give up small value, and the effect dey compound over months. The panels above measure the outcome for the windows dem cover.
VXX fit go to zero?
The quoted price dey get support from reverse splits: whenever e too low, four shares turn one and the price multiply by four. The split panel above count how many times e happen. Separately, ETNs get maturity date and often an issuer call right, so a note fit end before the holder plan to sell.
Wetin make ETN different from ETF?
An ETF dey hold assets inside a fund with a custodian. An ETN na unsecured note from a bank, so wetin you hold na the issuer credit plus the index return. If issuance stop, the market price fit trade away from the indicative value.
Every panel here carry the exact SQL under am, open any one and see how the number come. If you wan run the same measure for another ticker or another window, ask the question for plain English on the Strasmore terminal.