Lesson 3.2.3 · 60 min
Rate and index spreads: 2s10s, NOB, NQ/ES and Europe versus the U.S.
With bond futures you bet on the slope of the curve without betting on the level of rates, and with index futures, on one market against another without betting on the stock market. In both cases the ratio between the legs decides what really remains in the position. This lesson builds the DV01-neutral 2s10s steepener and NOB, the notional-neutral and beta-neutral NQ/ES and the Europe versus U.S. spread, and measures what exposure they are left with.
- Module
- 3.2 · Futures spreads
- Duration
- 60 min
- Prerequisites
- 3.2.1 · Calendar spreads, butterflies and condors, 1.2.7 · Fixed income and interest rates; CFDs and leveraged products
- Author
- Jesús Cuesta
- Updated
Level 3 lessons
3.1 · Futures in depth
3.2 · Futures spreads
- 3.2.1 Calendar spreads, butterflies and condors
- 3.2.2 Intercommodity spreads: crack, spark and crush
- 3.2.3 Rate and index spreads: 2s10s, NOB, NQ/ES and Europe versus the U.S.
- 3.2.4 Hedge ratios: by notional, by DV01 and by volatility
- 3.2.5 Spread data and backtesting: listed, synthetic and legged
- 3.2.6 Seasonality of spreads: multi-year analysis, patterns and traps
3.3 · Advanced forex
3.4 · Option theory and pricing
- 3.4.1 Payoffs, put-call parity and arbitrage bounds
- 3.4.2 Binomial trees, Black-Scholes-Merton, Black-76 and Monte Carlo
- 3.4.3 Greeks: delta, gamma, vega, theta, rho, vanna, volga and charm
- 3.4.4 Implied volatility: Newton-Raphson, Brent, py_vollib and QuantLib
- 3.4.5 Smile, skew and term structure; volatility surface with SVI
- 3.4.6 Realized vs implied volatility; volatility risk premium; VIX and VSTOXX
- 3.4.7 Advanced models: Heston, SABR and local volatility
3.5 · Option structures in Python
- 3.5.1 Directional and vertical structures: call, put, covered call, collar and spreads
- 3.5.2 Volatility and range structures: straddles, strangles, condors and butterflies
- 3.5.3 Calendars, diagonals, ratios, backspreads, risk reversals and jade lizard
- 3.5.4 A custom tool: payoff, aggregate Greeks and scenarios
- 3.5.5 Management: adjustments, rolls, early closes, early assignment and pin risk
3.6 · Systematic volatility and options strategies
3.7 · Crypto derivatives and specific strategies
- 3.7.1 Perpetuals: funding mechanics, mark price and liquidations
- 3.7.2 Funding arbitrage, basis with futures and cross-exchange arbitrage
- 3.7.3 Crypto options, on-chain data and DeFi
- 3.7.4 ccxt for trading on multiple exchanges
- 3.7.5 MiCA: the EU framework for crypto-assets and their service providers (CASPs)
Betting on the slope, not on the level
The 2s10s slope is the difference between the 10-year yield and the 2-year yield (lesson 1.2.7). A view on it (that the curve will steepen, or flatten) is not a view on rates: the curve can steepen with rising rates (the 10-year rises more) or with falling rates (the 2-year falls more). To trade only the slope with futures you have to buy one and sell another in such a way that a parallel move of the whole curve neither gains nor loses.
The tool is the DV01 of each future: how many dollars a contract gains or loses if the yield of its reference bond
falls one basis point. The data (tipos3_dv01.csv) give it for the contract held of each rate future. They are
synthetic data: TPA, TPB, TPC and TPD imitate the U.S. Treasury 2, 5 and 10-year notes and bond (ZT, ZF, ZN,
ZB), and TPE the Bund; each contract is the forward price of a standard bond with a 6% coupon (the model's “CTD”,
with a conversion factor of 1).
import numpy as np
import pandas as pd
dv = pd.read_csv("tipos3_dv01.csv", parse_dates=["fecha"])
cols = ["mercado", "contrato", "liquidacion", "rendimiento_ctd",
"vencimiento_ctd_anos", "duracion_modificada", "dv01"]
dv.loc[dv["fecha"] == "2025-12-31", cols].set_index("mercado") contrato liquidacion rendimiento_ctd vencimiento_ctd_anos duracion_modificada dv01
mercado
TPA TPAH26 104.273438 3.6651 2.147 2.040 42.55
TPB TPBH26 108.750000 3.7311 4.447 3.973 43.21
TPC TPCH26 112.546875 3.8286 6.816 5.729 64.47
TPD TPDH26 121.625000 4.1319 16.216 11.056 134.46
TPE TPEH26 126.910000 2.5060 8.878 7.240 91.88A TPC contract gains or loses 64.47 USD per basis point; a TPA one, 42.55, even though its notional is twice as
large (200,000 versus 100,000): the 2-year bond is much less sensitive to rates. To match the DV01 of one TPC
contract you need TPA contracts. That is the DV01-neutral hedge:
where “short” and “long” refer to the maturity, not to the sign: the steepener is long contracts of the short maturity and short one of the long maturity.
Mermaid source
flowchart TB M[Curve moves] --> P[Parallel] M --> E[Steepens] M --> A[Flattens] P --> P0[Steepener: 0] E --> E1[Steepener: gains] A --> A1[Steepener: loses]
The NOB (notes over bonds) is the same spread between the 10-year note and the bond. The ratio is not fixed: the DV01 of each future changes with the level of rates and with the bond that is delivered.
d01 = dv.pivot(index="fecha", columns="mercado", values="dv01")
ratios = pd.DataFrame({"2s10s (TPA per TPC)": d01["TPC"] / d01["TPA"],
"NOB (TPC per TPD)": d01["TPD"] / d01["TPC"]})
print(ratios.describe().loc[["min", "50%", "max"]].round(2))
ratios.resample("YE").mean().round(2).T.iloc[:, ::3] 2s10s (TPA per TPC) NOB (TPC per TPD)
min 1.41 1.94
50% 1.59 2.23
max 1.87 2.93
fecha 2010-12-31 2013-12-31 2016-12-31 2019-12-31 2022-12-31 2025-12-31
2s10s (TPA per TPC) 1.52 1.55 1.62 1.68 1.56 1.53
NOB (TPC per TPD) 2.03 2.11 2.30 2.53 2.22 2.15In the data, the 2s10s needs between 1.41 and 1.87 TPA contracts for each TPC one, and the NOB between 1.94 and
2.93 TPC contracts for each TPD. CME lists these spreads as instruments with fixed ratios: 2:1 in the 2-year versus
the 10-year (TUT) and 2:1 in the 10-year versus the bond (NOB), among others, which according to CME itself are not
expected to change except for substantial market changes. A fixed ratio is convenient (a single order, a single
price), but it is only DV01-neutral when it matches the ratio of the DV01s. Hedges by notional, by DV01 and by
volatility, and how to choose among them, are the subject of lesson 3.2.4.
The DV01-neutral steepener
Before building the spread it is worth checking that the DV01 says what it promises. The daily P&L of a long in TPC
(with the same contracts from one day to the next, as in lesson 3.2.1), divided by the change in the yield of its
reference bond in basis points:
cur = pd.read_parquet("futuros3_curvas.parquet")
ctr = pd.read_csv("futuros3_contratos.csv",
parse_dates=["vencimiento", "fecha_roll"])
esp = pd.read_csv("futuros3_especificaciones.csv",
index_col="mercado")
def cambio(mercado, log=False):
"""Daily change of the contract held at the previous close
(the first that has not reached its fecha_roll; lesson 3.2.1)."""
c = cur[cur["mercado"] == mercado].merge(
ctr[["contrato", "vencimiento", "fecha_roll"]], on="contrato")
px = c.pivot(index="fecha", columns="contrato",
values="liquidacion")
d = (np.log(px) if log else px).diff().stack()
c = c[c["fecha"] < c["fecha_roll"]].sort_values(
["fecha", "vencimiento"])
ley = c.groupby("fecha")["contrato"].first().shift(1).dropna()
idx = pd.MultiIndex.from_arrays([ley.index, ley.to_numpy()])
return pd.Series(d.reindex(idx).to_numpy(), index=ley.index)
def pyg(mercado):
"""Daily P&L per contract, in the contract's currency."""
return cambio(mercado) * esp.loc[mercado, "multiplicador"]
usd_pb = pyg("TPC") / (dv[dv["mercado"] == "TPC"].set_index("fecha")
["rendimiento_ctd"].diff() * 100)
print(f"P&L of a long in TPC per bp rise in the CTD: "
f"{usd_pb.median():.1f} USD (mean DV01 "
f"{d01['TPC'].mean():.1f})")P&L of a long in TPC per bp rise in the CTD: -70.1 USD (mean DV01 70.4)A long in TPC loses a median 70.1 USD for every basis point the yield rises, and the mean DV01 of the series is
70.4. With that, the steepener:
yld = dv.pivot(index="fecha", columns="mercado",
values="rendimiento_ctd")
def empinador(corto, largo):
"""Long h contracts of the short maturity and short 1 of the long,
h = long DV01 / short DV01 of the previous session."""
h = (d01[largo] / d01[corto]).shift(1)
p = (h * pyg(corto) - pyg(largo)).dropna()
nivel = yld[largo].diff().reindex(p.index) * 100 # bp
pendiente = (yld[largo] - yld[corto]).diff().reindex(
p.index) * 100
return p, nivel, pendiente
p, nivel, pend = empinador("TPA", "TPC")
dp = (yld["TPC"] - yld["TPA"]).iloc[[0, -1]].diff().iloc[-1]
print(f"Cumulative P&L 2010-2025: {p.sum():,.0f} USD per TPC "
"contract")
print(f"Change in the CTD slope over the period: {100 * dp:+.0f} bp")
print(f"Correlation of the daily P&L with the change in slope: "
f"{p.corr(pend):.2f}; with the change in level: {p.corr(nivel):.2f}")Cumulative P&L 2010-2025: -29,452 USD per TPC contract
Change in the CTD slope over the period: -193 bp
Correlation of the daily P&L with the change in slope: 0.99; with the change in level: 0.49The figure at the top sums it up: between 2010 and 2025 the synthetic slope (yield of the 10-year reference bond minus
that of the 2-year) went from about 200 bp to negative values, with a total change of −193 bp, and the steepener lost
29,452 USD per TPC contract. Its daily P&L has a correlation of 0.99 with the change in slope. The cumulative P&L is
not exactly the slope times the DV01, because over 16 years the DV01s, the reference bond of each contract and the
financing of the two legs change; but day to day it is.
The correlation with the level (0.49) is not zero. Is the position neutral to the level or not? To separate the two things, a regression of the daily P&L on the change in the 10-year yield (“level”), alone and together with the change in slope:
def betas(p, nivel, pend):
filas = {}
for per, (a, b) in {"2010-2015": ("2010", "2015"),
"2016-2025": ("2016", "2025")}.items():
y, l, s = p.loc[a:b], nivel.loc[a:b], pend.loc[a:b]
sola = np.polyfit(l, y, 1)[0]
X = np.column_stack([np.ones(len(y)), l, s])
_, b_niv, b_pend = np.linalg.lstsq(X, y, rcond=None)[0]
filas[per] = {"nivel_sola": sola, "nivel_con_pend": b_niv,
"pendiente": b_pend}
return pd.DataFrame(filas).T.round(1)
pd.concat({"2s10s": betas(p, nivel, pend),
"NOB": betas(*empinador("TPC", "TPD"))}) nivel_sola nivel_con_pend pendiente
2s10s 2010-2015 34.0 -0.2 71.7
2016-2025 15.1 1.1 69.5
NOB 2010-2015 13.0 0.1 156.6
2016-2025 14.2 1.0 158.2With the slope in the regression, the beta to the level is almost zero (−0.2 and 1.1 USD per bp in the 2s10s; 0.1 and 1.0 in the NOB) and the beta to the slope is almost the DV01 of the long-maturity leg: 69.5-71.7 USD per bp in the 2s10s (DV01 of the 10-year, 70-71) and 156.6-158.2 in the NOB (DV01 of the bond, 155-163). It is the known answer from the data README, and the regression recovers it. The position is neutral to a parallel shift. But the beta to the level alone, without the slope, is 34 USD per bp in the 2s10s of 2010-2015 and 13-15 in the other cases. The explanation lies in how the two maturities moved:
dy = yld.diff() * 100
vol = dy.groupby(dy.index.year >= 2016)[["TPA", "TPC", "TPD"]].std()
vol.index = ["2010-2015", "2016-2025"]
vol.round(2)mercado TPA TPC TPD
2010-2015 4.00 6.22 6.33
2016-2025 6.95 7.13 7.30In 2010-2015, with short-term rates near zero, the 2-year yield moved with a daily standard deviation of 4.00 bp versus 6.22 for the 10-year. A rise in the 10-year was almost always a steepening, so, in practice, the steepener behaved largely like a short in the 10-year note. DV01-neutral means neutral to a parallel move, not neutral to what the curve actually does. From 2016, with the 2-year as volatile as the 10-year (6.95 versus 7.13 bp), the beta to the level alone falls to 15.
NQ/ES: one index against another
The most traded index spread in the U.S. is the Nasdaq-100 versus the S&P 500 (NQ/ES): a bet on tech stocks against
the broad market. In the data, RVB imitates the E-mini Nasdaq-100 and RVA the E-mini S&P 500. In the model, the log
return of each future is its own drift (7.0% a year in RVA, 9.5% in RVB), plus a beta to a common market factor
(1.00 and 1.15) and its own noise. With the same contracts from one day to the next:
r = pd.DataFrame({m: cambio(m, log=True)
for m in ["RVA", "RVB", "RVE"]}).dropna()
beta = r.cov().loc["RVB", "RVA"] / r["RVA"].var()
print(f"Beta of RVB to RVA: {beta:.3f}; correlation: "
f"{r['RVB'].corr(r['RVA']):.2f}")
for nombre, s in {"notional (1:1)": r["RVB"] - r["RVA"],
"beta": r["RVB"] - beta * r["RVA"]}.items():
media, vol = s.mean() * 252, s.std() * 252 ** 0.5
t = media / vol * (len(s) / 252) ** 0.5
print(f"Neutral by {nombre}: drift {media:+.1%}/year, "
f"vol {vol:.1%}, t = {t:.2f}, "
f"correlation with RVA {s.corr(r['RVA']):+.2f}")Beta of RVB to RVA: 1.151; correlation: 0.91
Neutral by notional (1:1): drift +3.2%/year, vol 10.4%, t = 1.21, correlation with RVA +0.28
Neutral by beta: drift +1.4%/year, vol 10.0%, t = 0.56, correlation with RVA +0.00The measured beta (1.151) recovers the planted one (1.15). There are two usual ways to build the spread:
- Notional-neutral (one dollar long for one dollar short): it is the one CME describes with its spread ratio,
the ratio of the notionals of the two contracts computed with the spot index. It keeps the difference in betas:
1.15 − 1 = 0.15 of the market. In the data, its correlation with
RVAis 0.28 and its drift, +3.2% a year. - Beta-neutral (1.15 dollars of
RVAper dollar ofRVB): it removes the market factor. Its correlation withRVAis 0.00 and its drift is the pure relative one, which in the model is % a year. The measured one is +1.4%.
The estimate of the beta-neutral drift is almost exact, and even so it means nothing: with a volatility of 10% a year and 16 years, the standard error of the mean is points, and . The notional-neutral spread looks better (t = 1.21, +50% cumulative in the figure), but its advantage comes almost entirely from the 0.15 of market it carries inside, which gains while the stock market rises and loses when it falls (the 2016 stretch of the figure is the most visible). It is the same point as in lesson 3.2.1 with the crude calendar: what is called a “spread” can be, in part, a directional position.
Converting to contracts:
idx = pd.read_csv("futuros3_indices_contado.csv",
parse_dates=["fecha"])
s = idx[idx["fecha"] == "2025-12-31"].set_index("indice")["contado"]
nominal = s[["RVA", "RVB"]] * esp.loc[["RVA", "RVB"], "multiplicador"]
print(nominal.round(0).to_string())
n_b = 1e6 / nominal["RVB"]
print(f"Long RVB: {n_b:.1f} contracts; short RVA notional-neutral: "
f"{n_b * nominal['RVB'] / nominal['RVA']:.1f}; "
f"beta-neutral: {beta * n_b * nominal['RVB'] / nominal['RVA']:.1f}")indice
RVA 335966.0
RVB 435294.0
Long RVB: 2.3 contracts; short RVA notional-neutral: 3.0; beta-neutral: 3.4One million USD in RVB is 2.3 contracts (435,294 USD of notional each as of 2025-12-31); the short side, 3.0 RVA
contracts notional-neutral or 3.4 beta-neutral. With large contracts, a one-million spread cannot be sized precisely:
the micros (RVAM, RVBM, a tenth of the multiplier, lesson 3.1.1) exist, among other things, for that. And the beta
is not fixed: the second exercise measures it year by year.
Europe versus the U.S.: the currency
The Europe versus U.S. spread adds a difficulty: the legs are quoted in different currencies. In the data, RVE
imitates the Euro Stoxx 50 and is quoted in QEV (the Vesperian evro, which imitates the euro); RVA, in USD. If an
investor buys the European stocks with dollars, they have the European index and also the currency: their return in
USD is that of the index in QEV plus that of the QEV against the USD. With a future there is no need to exchange the
notional: a margin is posted and the P&L is settled every day, in QEV. The currency risk is limited to that
accumulated P&L and to the margin.
Mermaid source
flowchart LR C[European cash] --> N[Notional in QEV] N --> X1[Fully exposed] F[RVE future] --> P[Result in QEV] P --> X2[Only the result]
fx = pd.read_parquet("fx3_diario.parquet")
x = fx[fx["divisa"] == "QEV"].set_index("fecha")["usd_por_unidad"]
r_fx = np.log(x).diff().reindex(r.index)
contado_usd = r["RVE"] + r_fx # European index converted to USD
futuro_usd = np.expm1(r["RVE"]) * x.reindex(r.index) / x.shift(
1).reindex(r.index) # P&L of the future, in USD
for nombre, s in {"RVE in QEV": r["RVE"],
"RVE in USD (cash)": contado_usd,
"RVE future, P&L in USD": futuro_usd}.items():
print(f"{nombre:24s} vol {s.std() * 252 ** 0.5:.1%} "
f"correlation with RVA {s.corr(r['RVA']):.2f}")RVE in QEV vol 20.9% correlation with RVA 0.86
RVE in USD (cash) vol 22.9% correlation with RVA 0.78
RVE future, P&L in USD vol 20.9% correlation with RVA 0.86In QEV, the European index has a volatility of 20.9% and a correlation of 0.86 with RVA. Converted to USD as cash,
the volatility rises to 22.9% and the correlation falls to 0.78: the currency adds noise that has nothing to do with
the stock market. The P&L of the future converted to USD each day stays like the index in QEV (20.9% and 0.86). A
Europe versus U.S. spread with futures is, therefore, almost a spread in local currency; with cash, it is also a
position in the currency. How to manage that risk in a multi-currency portfolio is the subject of lesson 3.3.3.
What this changes in a system
- The ratio decides the bet. DV01-neutral, the position bets on the slope; with another ratio, also on the level. Notional-neutral, an index spread also bets on the market; beta-neutral, it does not.
- Neutral to one move is not neutral to all. Near zero rates, a DV01-neutral steepener has a beta to the level of 34 USD per bp. The residual exposure is measured on data from the regime, with a regression.
- Ratios move. The DV01 and the beta change over time; listed spreads with a fixed ratio are convenient, but not always neutral. Redoing the ratio every day has an execution cost (lesson 3.2.5).
- A relative drift is not validated with 16 years. With 10% volatility, you need a drift of more than 5 points a year for the t to exceed 2.
- The currency, only in the P&L. With futures, the currency risk is that of the P&L and the margin; with cash, that of the notional.
Exercises
- Build the 2s10s with the fixed 2:1 ratio (two
TPAcontracts for oneTPC) and repeat the beta regression. What exposure to the level remains with the slope in the regression and why does it have that sign?
Solution
p_fijo = (2 * pyg("TPA") - pyg("TPC")).dropna()
betas(p_fijo, nivel.reindex(p_fijo.index),
pend.reindex(p_fijo.index)) nivel_sola nivel_con_pend pendiente
2010-2015 23.8 -19.6 91.1
2016-2025 1.0 -16.6 87.7With 2:1, the beta to the level with the slope in the regression is no longer zero: −19.6 USD per bp in 2010-2015 and
−16.6 in 2016-2025. The sign is negative because two TPA contracts have more DV01 than one TPC contract
(2 × 42.55 = 85.1 versus 64.47 at the end of 2025): the position is net long duration and loses when rates rise in
parallel. The beta to the slope rises to 88-91 USD per bp because the short-maturity side, with more contracts, weighs
more. With the fixed ratio you bet on the slope and, in addition, on a fall in rates.
- Estimate the beta of
RVBtoRVAin each year from 2010 to 2025. How much does it vary and what consequence does it have for a beta-neutral spread calibrated with one year of data?
Solution
por_ano = r.groupby(r.index.year).apply(
lambda g: g["RVB"].cov(g["RVA"]) / g["RVA"].var())
print(por_ano.round(2).to_frame("beta").T.to_string())
print(f"From {por_ano.min():.2f} to {por_ano.max():.2f}")fecha 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025
beta 1.15 1.21 1.15 1.12 1.13 1.15 1.14 1.15 1.17 1.06 1.15 1.1 1.15 1.19 1.16 1.17
From 1.06 to 1.21The annual beta ranges from 1.06 (2019) to 1.21 (2011), around the true value of 1.15, which does not change in the
model: all the variation is estimation error with about 250 sessions. A spread calibrated with the 2019 beta would have
been 8% short in RVA (1.06 versus 1.15), with a residual exposure of 0.09 to the market. In real data the beta also
truly changes, so estimation with short windows mixes the two effects: more noise with short windows, more lag with
long windows (the Kalman filter of lesson 2.1.6 is one way to choose).
- A manager with a portfolio of European stocks in USD wants to bet that Europe will outperform the U.S. without adding currency risk. Compare doing it with futures (long the European future, short the U.S. one) and with cash (buying European stocks and selling a U.S. ETF).
Solution
With futures, the notional is not converted into another currency: the manager posts margin in QEV (or in USD, depending on the broker) and receives or pays every day the P&L of the European leg in QEV. Their currency exposure is that of the accumulated P&L and the margin, a small fraction of the notional; in the data, the P&L of the future converted to USD has the same volatility as the index in QEV (20.9%). With cash, they buy stocks in QEV with the whole notional and are exposed to the currency for the full amount: the European index in USD has 22.9% volatility and a lower correlation with the U.S. (0.78 versus 0.86). To have only the relative bet with cash they would have to hedge the currency separately (with a forward, lesson 3.3.3). The cost of the futures version lies elsewhere: two clearing houses with no margin offset, different trading hours and the roll of both legs every quarter.
Each answer is folded under its question
Self-assessment
A DV01-neutral 2s10s steepener is long 2-year notes and short 10-year notes. When does it gain?
- AWhen all rates rise by the same amount
- BWhen the slope of the curve rises: the 10-year yield rises more (or falls less) than the 2-year
- CWhen rates fall
- DWhen the curve flattens
Show answer
Answer B. When the slope of the curve rises: the 10-year yield rises more (or falls less) than the 2-year
With the same dollars per basis point in both legs, a parallel shift cancels out. What remains is the slope: in the data, the beta of the P&L to the slope is 69.5-71.7 USD per bp, almost the DV01 of the 10-year note (70-71), and the daily correlation with the change in slope, 0.99.
In 2010-2015, a regression of the steepener's P&L on the change in the 10-year yield gives a beta of 34 USD per bp; with the slope in the regression, −0.2. What does it indicate?
- AThat the DV01 hedge is miscalculated
- BThat the position is not neutral to the level
- CThat the 2-year moved more than the 10-year
- DThat it is neutral to a parallel shift, but level and slope did not move in the same way: near zero rates the 2-year barely moved, and a rise in the 10-year was almost always a steepening
Show answer
Answer D. That it is neutral to a parallel shift, but level and slope did not move in the same way: near zero rates the 2-year barely moved, and a rise in the 10-year was almost always a steepening
The beta alone mixes level and slope. In 2010-2015 the daily standard deviation of the 2-year yield was 4.00 bp versus 6.22 for the 10-year: when the 10-year rose, the curve steepened. With the slope in the regression, the beta to the level is −0.2: the position is indeed neutral to a parallel move.
CME lists the NOB (10-year notes versus the bond) with a fixed 2:1 ratio. In the data, the DV01 ratio ranges from 1.94 to 2.93. What does trading with the fixed ratio imply?
- ANothing: both are neutral
- BThat the fixed ratio always has less risk
- CThat the position is only DV01-neutral when the ratio of the DV01s is close to 2; the rest of the time an exposure to the level remains
- DThat the DV01 ratio is an error in the data
Show answer
Answer C. That the position is only DV01-neutral when the ratio of the DV01s is close to 2; the rest of the time an exposure to the level remains
The DV01 of each future changes with the level of rates and with the cheapest-to-deliver bond. A fixed ratio is convenient to execute in a single instrument, but it leaves exposure to the level when it drifts away from the DV01 ratio. The first exercise measures it in the 2s10s with a 2:1 ratio: −17 to −20 USD per bp of exposure to the level.
The beta-neutral (1.15) RVB/RVA spread has a measured drift of +1.4% a year with a volatility of 10% over 16 years (t = 0.56). The planted drift is 1.45%. What do you conclude?
- AThat the estimate is almost exact, but 16 years are not enough to distinguish it from zero: the standard error of the mean is about 2.5 points a year
- BThat there is no drift
- CThat there is drift and it is significant
- DThat the beta is badly estimated
Show answer
Answer A. That the estimate is almost exact, but 16 years are not enough to distinguish it from zero: the standard error of the mean is about 2.5 points a year
With a volatility of 10% a year, the standard error of an annual mean estimated with 16 years is 10/√16 = 2.5 points. A real drift of 1.45% is 0.6 standard errors away from zero. In real data the truth is not known: an index spread with a drift like that cannot be validated with its own history.
A spread long the European index future RVE (in QEV) and short RVA (in USD). What currency risk does it have?
- AOnly that of the accumulated P&L and the margin in QEV: a future does not invest the notional, so its P&L in USD has the volatility of the index in QEV (20.9%), not that of the index converted to USD (22.9%)
- BThat of the entire notional of the European leg, as if the stocks had been bought
- CNone
- DTwice that of cash
Show answer
Answer A. Only that of the accumulated P&L and the margin in QEV: a future does not invest the notional, so its P&L in USD has the volatility of the index in QEV (20.9%), not that of the index converted to USD (22.9%)
With futures the notional is not exchanged into QEV: margins are posted and the P&L is settled. The P&L in USD is the P&L in QEV times the day's exchange rate, and its volatility is that of the index in QEV. European cash converted to USD has more volatility (22.9%) and less correlation with RVA (0.78 versus 0.86).
Key points
- A DV01-neutral rate spread equalizes the dollars per basis point of the two legs: it neither gains nor loses with a parallel shift and its P&L follows the slope (beta of 70 USD per bp, correlation of 0.99).
- DV01-neutral is not level-neutral in a simple regression: near zero rates the 2-year barely moves, and a steepener behaves partly like a short in the 10-year (beta of 34 USD per bp in 2010-2015).
- The DV01 ratio moves (1.41-1.87 in the 2s10s, 1.94-2.93 in the NOB of the data); listed spreads use fixed ratios and leave exposure to the level when they drift away.
- A notional-neutral index spread keeps the difference in betas (correlation of 0.28 with the market); a beta-neutral one does not (0.00). Its drift, even when planted, cannot be distinguished from zero with 16 years.
- With futures, a spread between indices in different currencies only has currency risk in the P&L and the margin, not in the notional.
Resources
Documentation
- CME Group: Interest Rate Futures Inter-Commodity Spreads (fixed ratios of the TUT, NOB and other Treasury spreads)
- CME Group Client Systems Wiki: Spreads and Combinations Available on CME Globex (price of inter-commodity spreads)
- CME Group: Stock Index Spread Opportunities (ratio of a spread between indices by notional value)
- CME Group: Trading Opportunities in Equity Index Futures (Nasdaq-100 versus S&P 500 spread)