Skip to content

Instantly share code, notes, and snippets.

@timelyportfolio
Last active February 19, 2023 23:01
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save timelyportfolio/4da9d6b6c89cce26effabccca30124dd to your computer and use it in GitHub Desktop.
Save timelyportfolio/4da9d6b6c89cce26effabccca30124dd to your computer and use it in GitHub Desktop.
3d yield curve with Plotly in R

Nowhere near as spectacular as the Upshot/New York Times 3d yield curve by Amanda Cox and Gregor Aisch, but not bad at all for a couple of lines of R code with the plotly htmlwidget.

library(plotly)
library(dplyr)
library(tidyr)
library(purrr)
library(quantmod)
library(magrittr)


# get yields from St. Louis Fed FRED
yield_curve <- list("DTB3", "DGS2", "DGS5", "DGS10", "DGS30") %>%
  map(
    ~getSymbols(.x, auto.assign=FALSE, src="FRED")
  ) %>%
  do.call(merge,.)

# create our 3d surface yield curve
yield_curve["1980::"] %>%
  # convert to numeric matrix
  data.matrix() %>% 
  # transpose
  t() %>%
  # draw our Plotly 3d surface
  plot_ly(
    x=as.Date(index(yield_curve["1980::"])),
    y=c(0.25,2,5,10,30),
    z=.,
    type="surface"
  ) %>%
  plotly::layout(
    scene=list(
      xaxis=list(title="date"),
      yaxis=list(title="term"),
      zaxis=list(title="yield")
    )
  )

  
# 3d scatter chart
yield_curve_tidy <- yield_curve %>%
  data.frame() %>%
  add_rownames(var="date") %>%
  gather(symbol,yield,-date) %>%
  mutate(term=c(0.25,2,5,10,30)[match(symbol,colnames(yield_curve))])

yield_curve_tidy[which(!is.na(yield_curve_tidy$yield)),] %>%
  group_by(symbol) %>%
  plot_ly(
    x = ~date, y = ~term, z = ~yield,
    type="scatter3d",
    mode="markers",
    size=3,
    color=~yield
  )

library(plotly)
library(dplyr)
library(tidyr)
library(purrr)
library(quantmod)
library(magrittr)
# get yields from St. Louis Fed FRED
yield_curve <- list("DTB3", "DGS2", "DGS5", "DGS10", "DGS30") %>%
map(
~getSymbols(.x, auto.assign=FALSE, src="FRED")
) %>%
do.call(merge,.)
# create our 3d surface yield curve
yield_curve["1980::"] %>%
# convert to numeric matrix
data.matrix() %>%
# transpose
t() %>%
# draw our Plotly 3d surface
plot_ly(
x=as.Date(index(yield_curve["1980::"])),
y=c(0.25,2,5,10,30),
z=.,
type="surface"
) %>%
plotly::layout(
scene=list(
xaxis=list(title="date"),
yaxis=list(title="term"),
zaxis=list(title="yield")
)
)
# 3d scatter chart
yield_curve_tidy <- yield_curve %>%
data.frame() %>%
add_rownames(var="date") %>%
gather(symbol,yield,-date) %>%
mutate(term=c(0.25,2,5,10,30)[match(symbol,colnames(yield_curve))])
yield_curve_tidy[which(!is.na(yield_curve_tidy$yield)),] %>%
group_by(symbol) %>%
plot_ly(
x = ~date, y = ~term, z = ~yield,
type="scatter3d",
mode="markers",
size=3,
color=~yield
)
@masoumehsolgi
Copy link

hi,
thanks for your code, but I can not understand this line of your code
yield_curve["1980::"] ,
please help me

@timelyportfolio
Copy link
Author

"1980::" means from 1980 to end. See xts. Let me know if this isn't clear.

@ntankova
Copy link

ntankova commented Jun 4, 2020

Hi,

the code at line 43 is wrong:
mutate(term=c(0.25,5,10,30)[match(symbol,paste0(c("IRX","FVX","TNX","TYX"),".Close"))])

the function match returns a vector of the positions of (first) matches of its first argument in its second, and here match returns 0,
because column symbol have values "DTB3" "DGS2" "DGS5" "DGS10" "DGS30", and the match() is looking for "IRX.Close" "FVX.Close" "TNX.Close" "TYX.Close".
The result is no match, integer 0.

column symbol contains the symbols for US Treasury bills, https://fred.stlouisfed.org/:
#DTB3 (3-Month Treasury Bill)
#DGS2 (2-Year Treasury Constant Maturity Rate)
#DGS5 (5-Year Treasury Constant Maturity Rate)
#DGS10 (10-Year Treasury Constant Maturity Rate)
#DGS30 (30-Year Treasury Constant Maturity Rate)

"IRX","FVX","TNX","TYX" are symbols of the interest rate options on US Treasury bills.
http://www.marketswiki.com/wiki/CBOE_interest_rate_products
#The Chicago Board Options Exchange offered four interest rate options products representing short-, medium- and long-term rates on:
#13-Week Treasury bills (IRX)
#5-Year Treasury notes (FVX)
#10-Year Treasury notes (TNX)
#30-Year Treasury bonds (TYX)
#These products have been delisted.

@timelyportfolio
Copy link
Author

@ntankova thanks for the comment. This code is pretty old, and I'm surprised that it works at all :) I think when I posted I was trying to show different ways of getting yields at various maturities and did not include the code for IRX, FVX, etc. These indices still exist and are available, but you are correct that the options on them no longer trade.

I made changes in https://gist.github.com/timelyportfolio/4da9d6b6c89cce26effabccca30124dd/revisions to hopefully get the code working again only using the Federal Reserve series on yields as we did in the surface chart.

@ntankova
Copy link

ntankova commented Jun 4, 2020

The final 3-d scatter plot needs the argument:

mode = 'markers'

This code is used for teaching, as it is.
I am a student.
I found an error and searched for the origin of the code, for check.

Thank you.

@timelyportfolio
Copy link
Author

@ntankova I commend you on your drive to look into the error, report the error, and comment. Thanks. I made a couple more changes while we are at it, but in general I think the 3d scatter is not all that helpful compared to the surface chart.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment