Project Development for plotting and analyzing CFTC data.

Premise: Commitments of Traders Futures Data may give insight into future price action for some Fx Pairs and commodites. This information may possibly be packaged in a way that could be sold for a subscription.

Background: Steven Jon Kaplan (SVK), who runs the website and service at https://www.truecontarian.com, frequently uses extremes in commitments of traders for commercial and non-commerical traders to make trades. Recent example as of 15 Sep 2024: Steven is long palladium do to extreme long interest by commercial traders.
This project will attempt to collect data on commitments of traders and display in a manner usable for making investment decisions.
Ideas:
29 SEP 2024:
-Show commercial and non-commercial traders by long and short
-Show net long or short for traders
-Show a ratio of long vs. short by trader type
-Find historical extremes; perhaps by last year, last xx years, all time
-Compare to price
-Make maximum gain or loss over the next xx months; 3, 6, 12, 18?

Example

This screenshot below is from the website: http://cotpricecharts.com SVK subscribed to this and would occasionally share some information from the website and would sometimes make trades when commitments of traders seemed to hit extremes for some assets.
The website is no longer active. The person who maintained the webiste and updated it passed away and no one took his place to maintain it.

https://www.appsilon.com/post/r-markdown-tips#images
https://www.earthdatascience.org/courses/earth-analytics/document-your-science/add-images-to-rmarkdown-report/

Old example from http://cotpricecharts.com by Software North
Old example from http://cotpricecharts.com by Software North

To do: get a picture of a current website.
xxxxxxx

www.cftc.gov has this kind of data. Looks like this…
To do: show a screenshot of current data from cftc.gov

Goal: create something that might look like this but also shows max gains and losses. Perhaps out to 6 months and 12 months???

Step 1: look around www.cftc.gov

Go Commitments of Traders here: https://www.cftc.gov/MarketReports/CommitmentsofTraders/index.htm
Credit to Steven Jon Kaplan of True Contrarian at https://truecontrarian-sjk.blogspot.com

Step 2: Figure out webscraping.

Here are websites for help with webscraping:

https://r4ds.hadley.nz/webscraping
https://preettheman.medium.com/best-web-scraping-packages-for-r-2787979b747
https://scrapingant.com/blog/r-web-scraping
https://steviep42.github.io/webscraping/book/
https://statsandr.com/blog/web-scraping-in-r/
https://www.zenrows.com/blog/web-scraping-r
https://www.bigbookofr.com/chapters/getting%20cleaning%20and%20wrangling%20data
https://oxylabs.io/blog/web-scraping-r
https://brightdata.com/blog/how-tos/web-scraping-with-r

15 Sep 2024: Might not need web-scraping as there is a new file each week.

Step 2 complete/not required

Get something working. Because SVK is current active trading palladium, we will start with that commodity.

Download data. Historical and recent data that can be downloaded in Excel format can be found on this link: https://www.cftc.gov/MarketReports/CommitmentsofTraders/HistoricalCompressed/index.htm

We download all of these files except the one “Starting July 20, 2010”.
jkk The 2006-2016 file actually downloads a folder containing three files with different years: 1986-2006, 2007-2014, and 2015-2016. We save all of these files to our R working directory and rename them by year.

Screenshot of the sizes of files from cftc.gov
Screenshot of the sizes of files from cftc.gov

As one can see, they files are a bit large.

Picking one at random (2015-2016), let’s get a plot of something.

But first, what is the Commitment of Traders data? Here is what recent data from cftc.gov webiste looks like for palladium:

Screenshot of Palladium Commintments of Traders from 17 Sep 2024
Screenshot of Palladium Commintments of Traders from 17 Sep 2024

Generally:
- “Non-Commercial” are entities like hedge funds and those who manage other people’s money
- “Commercial” are those that use palladium as part of their business and banks
- “Nonreportable” are individual traders

Let’s look at Commercial

https://www.tidyverse.org/packages/

library(tidyverse) # to use tidy data  
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readxl) # to read in Excel format data  
# Read Excel file
fullFile_FUT15_16 <- read_xls("FUT15_16.xls")
fullFile_FUT15_16
## # A tibble: 24,044 × 126
##    Market_and_Exchange_Names       As_of_Date_In_Form_Y…¹ Report_Date_as_MM_DD…²
##    <chr>                           <chr>                  <dttm>                
##  1 WHEAT-SRW - CHICAGO BOARD OF T… 161227                 2016-12-27 00:00:00   
##  2 WHEAT-SRW - CHICAGO BOARD OF T… 161220                 2016-12-20 00:00:00   
##  3 WHEAT-SRW - CHICAGO BOARD OF T… 161213                 2016-12-13 00:00:00   
##  4 WHEAT-SRW - CHICAGO BOARD OF T… 161206                 2016-12-06 00:00:00   
##  5 WHEAT-SRW - CHICAGO BOARD OF T… 161129                 2016-11-29 00:00:00   
##  6 WHEAT-SRW - CHICAGO BOARD OF T… 161122                 2016-11-22 00:00:00   
##  7 WHEAT-SRW - CHICAGO BOARD OF T… 161115                 2016-11-15 00:00:00   
##  8 WHEAT-SRW - CHICAGO BOARD OF T… 161108                 2016-11-08 00:00:00   
##  9 WHEAT-SRW - CHICAGO BOARD OF T… 161101                 2016-11-01 00:00:00   
## 10 WHEAT-SRW - CHICAGO BOARD OF T… 161025                 2016-10-25 00:00:00   
## # ℹ 24,034 more rows
## # ℹ abbreviated names: ¹​As_of_Date_In_Form_YYMMDD, ²​Report_Date_as_MM_DD_YYYY
## # ℹ 123 more variables: CFTC_Contract_Market_Code <chr>,
## #   CFTC_Market_Code <chr>, CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>,
## #   Open_Interest_All <dbl>, NonComm_Positions_Long_All <dbl>,
## #   NonComm_Positions_Short_All <dbl>, NonComm_Postions_Spread_All <dbl>,
## #   Comm_Positions_Long_All <dbl>, Comm_Positions_Short_All <dbl>, …

This has all data. 24,044 rows and 126 columns. And in tibble data format.
Limit to palladium:

# Just palladium
palladium_FUT15_16 <- fullFile_FUT15_16 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))
palladium_FUT15_16
## # A tibble: 104 × 126
##    Market_and_Exchange_Names       As_of_Date_In_Form_Y…¹ Report_Date_as_MM_DD…²
##    <chr>                           <chr>                  <dttm>                
##  1 PALLADIUM - NEW YORK MERCANTIL… 161227                 2016-12-27 00:00:00   
##  2 PALLADIUM - NEW YORK MERCANTIL… 161220                 2016-12-20 00:00:00   
##  3 PALLADIUM - NEW YORK MERCANTIL… 161213                 2016-12-13 00:00:00   
##  4 PALLADIUM - NEW YORK MERCANTIL… 161206                 2016-12-06 00:00:00   
##  5 PALLADIUM - NEW YORK MERCANTIL… 161129                 2016-11-29 00:00:00   
##  6 PALLADIUM - NEW YORK MERCANTIL… 161122                 2016-11-22 00:00:00   
##  7 PALLADIUM - NEW YORK MERCANTIL… 161115                 2016-11-15 00:00:00   
##  8 PALLADIUM - NEW YORK MERCANTIL… 161108                 2016-11-08 00:00:00   
##  9 PALLADIUM - NEW YORK MERCANTIL… 161101                 2016-11-01 00:00:00   
## 10 PALLADIUM - NEW YORK MERCANTIL… 161025                 2016-10-25 00:00:00   
## # ℹ 94 more rows
## # ℹ abbreviated names: ¹​As_of_Date_In_Form_YYMMDD, ²​Report_Date_as_MM_DD_YYYY
## # ℹ 123 more variables: CFTC_Contract_Market_Code <chr>,
## #   CFTC_Market_Code <chr>, CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>,
## #   Open_Interest_All <dbl>, NonComm_Positions_Long_All <dbl>,
## #   NonComm_Positions_Short_All <dbl>, NonComm_Postions_Spread_All <dbl>,
## #   Comm_Positions_Long_All <dbl>, Comm_Positions_Short_All <dbl>, …

A quick first plot of Commercial Long:
https://ggplot2-book.org/layers

# Plot long commercial positions vs date
library(ggplot2)
comm_long <- ggplot(palladium_FUT15_16, aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Long_All)) +
  geom_line()
plot(comm_long)

Add Commercial Short to plot:

# Next, add commercial short positions also on same plot
comm_long_short <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Long_All)) +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Short_All))
plot(comm_long_short)

Quick eyeball analysis for 2015-2016: Commercial Short positions are ALWAYS larger than Commercial Long positions.
Need to clean up: add key for two lines, correct y-axis label, clean up x-axis label.
Note: adding a legend for multiple lines in ggplot2 requires adding aes info as discussed here: https://stackoverflow.com/questions/40833809/add-legend-to-geom-line-graph-in-r and here: https://www.geeksforgeeks.org/add-legend-for-multiple-lines-in-r-using-ggplot2/

# Make a plot with palladium data  
comm_long_short <- ggplot(palladium_FUT15_16)  +
  # line for Commercial Long
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Long_All, colour = "Commercial Long")) +
  # line for Commercial Short
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Short_All, colour = "Commercial Short")) +
  # add label
  labs(
    y="Commercial Interest",
    x="Date"
  )
# show plot. 
plot(comm_long_short)

That works.
Clean up some more:

# Make a plot with palladium data  
comm_long_short <- ggplot(palladium_FUT15_16)  +
  # line for Commercial Long
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # add label
  labs(
    y="Commercial Interest",
    x="Date",
    title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# show plot. 
plot(comm_long_short)

That looks OK for now.
Lets look at a ratio of Commercial Long to Commercial Short interest:
Need to use mutate:
https://cran.r-project.org/web/packages/dplyr/vignettes/rowwise.html
https://dplyr.tidyverse.org/articles/rowwise.html

# Add a ratio of long to short
palladium_FUT15_16 <- palladium_FUT15_16 %>% mutate(long_short_ratio = Comm_Positions_Long_All/Comm_Positions_Short_All)


comm_long_short_ratio <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=long_short_ratio))
plot(comm_long_short_ratio)

And also Commercial Short to Commercial Long:

# Add a ratio of long to short and short to long
palladium_FUT15_16 <- palladium_FUT15_16 %>% mutate(long_short_ratio = Comm_Positions_Long_All/Comm_Positions_Short_All) %>% mutate(short_long_ratio = Comm_Positions_Short_All/Comm_Positions_Long_All)


comm_long_short_ratio <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=long_short_ratio))
plot(comm_long_short_ratio)

comm_short_long_ratio <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=short_long_ratio))
plot(comm_short_long_ratio)

Looks OK.
Let’s clean up some:

comm_long_short_ratio <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=long_short_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  )
plot(comm_long_short_ratio)

comm_short_long_ratio <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=short_long_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  )
plot(comm_short_long_ratio)

Let’s try to plot all together:

Note: par will plot multiple plots together in the same image but is base R and does not work with ggplot2. Need to try package cowplot or patchwork.
https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html
https://patchwork.data-imaginist.com

# par(mfrow = c(2,2)) only works in base R
# need another package to link plots together: patchwork
# other patchwork info:
# https://cran.r-project.org/web/packages/patchwork/vignettes/patchwork.html
# https://patchwork.data-imaginist.com
# https://mattherman.info/blog/ppt-patchwork/
library(patchwork)
comm_long_short / comm_long_short_ratio

All three together:

# par(mfrow = c(2,2)) only works in base R
# need another package to link plots together: patchwork
# other patchwork info:
# https://cran.r-project.org/web/packages/patchwork/vignettes/patchwork.html
# https://patchwork.data-imaginist.com
# https://mattherman.info/blog/ppt-patchwork/
comm_long_short_ratio / comm_short_long_ratio / comm_long_short

Change size of ratio charts:

# par(mfrow = c(2,2)) only works in base R
# need another package to link plots together: patchwork
# other patchwork info:
# https://cran.r-project.org/web/packages/patchwork/vignettes/patchwork.html
# https://patchwork.data-imaginist.com
# https://mattherman.info/blog/ppt-patchwork/
comm_long_short_ratio / comm_short_long_ratio / comm_long_short + plot_layout(heights = c(1,1,5))

Try to put a ratio on the same chart as the Long and Short interest.
This is actually very hard to do in ggplot2. Apparently, this is done on purpose as the makers of ggpolot2 don’t approve of plots with two axes. Seriously.
https://stackoverflow.com/questions/3099219/ggplot-with-2-y-axes-on-each-side-and-different-scales

# This y limit for long and short interest is static.  Need to make dynamic.
ylim.prim <- c(0,30000) #max of comm positions
# This y limit for ratio is static.  Need to make dynamic.
ylim.sec <- c(0,1) #ratio

b <- diff(ylim.prim)/diff(ylim.sec)
a <- ylim.prim[1] - b*ylim.sec[1]

comm_long_short_ratio_3 <- ggplot(palladium_FUT15_16, aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Long_All))  +
  geom_line() +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=Comm_Positions_Short_All)) +
  geom_line(aes(y = a + long_short_ratio*b), color = "red") +
  scale_y_continuous("Comm Positions", sec.axis = sec_axis(~ (. - a)/b, name = "Ratio")) +
  labs(
    x="Date",
    title = "Palladium Commercial Long & Short Interest and Ratio"
  )
plot(comm_long_short_ratio_3)

This works. But let’s try an interactive plot with plotly for R. https://plotly.com/r/

library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
ggplotly(comm_long_short)

And with ratio?

library(plotly)
ggplotly(comm_long_short_ratio_3)

That works, but will need some cleanup.
However, let’s try to stack the plots as before but make them interactive as above and all linked.
https://stackoverflow.com/questions/58103196/how-to-facet-a-plot-ly-chart

fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
figs_1and2 <- subplot(fig1, fig2)
figs_1and2

Now stacked:
https://plotly.com/r/subplots/
https://stackoverflow.com/questions/32955163/multiple-ggplot2-plots-with-plotly?rq=4

fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
figs_1and2 <- subplot(fig1, fig2, nrows = 2)
figs_1and2

Adding a “unified hover”:
https://stackoverflow.com/questions/66767067/how-to-change-order-of-r-plotly-hover-labels-with-x-unified-mode
https://stackoverflow.com/questions/69903147/how-to-link-traces-between-subplots-in-r-plotly-with-shared-y-axis-so-that-hover
https://stackoverflow.com/questions/54561931/r-plotly-link-subplots-so-that-multiple-tooltips-shown-on-hover
https://plotly.com/r/hover-text-and-formatting/
https://plotly.com/r/reference/layout/#layout-hovermode
https://community.plotly.com/t/announcing-plotly-r-4-9-2-9000-shape-drawing-unified-hover-and-rangebreaks/40086

fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
figs_1and2 <- subplot(fig1, fig2, nrows = 2) %>% layout(hovermode = "x unified")
figs_1and2
fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
figs_1and2 <- subplot(fig1, fig2, nrows = 2, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis")
figs_1and2
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

The second plot seems to work as best as able to make it.
Add the second ratio for comparison:

fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
fig3 <- ggplotly(comm_short_long_ratio)
figs_1_2_3 <- subplot(fig1, fig2, fig3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis")
figs_1_2_3
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

To Do: add subplot titles
Now, let’s show price of palladium ETF: PALL

library(tidyquant) # for downloading stock prices
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## ── Attaching core tidyquant packages ──────────────────────── tidyquant 1.0.9 ──
## ✔ PerformanceAnalytics 2.0.4      ✔ TTR                  0.24.4
## ✔ quantmod             0.4.26     ✔ xts                  0.14.0
## ── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
## ✖ zoo::as.Date()                 masks base::as.Date()
## ✖ zoo::as.Date.numeric()         masks base::as.Date.numeric()
## ✖ plotly::filter()               masks dplyr::filter(), stats::filter()
## ✖ xts::first()                   masks dplyr::first()
## ✖ dplyr::lag()                   masks stats::lag()
## ✖ xts::last()                    masks dplyr::last()
## ✖ PerformanceAnalytics::legend() masks graphics::legend()
## ✖ quantmod::summary()            masks base::summary()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# or maybe need library(quantmod) ???
# tidyquant includes quantmod
# Add a price of Palladium
# get Pall price
options("getSymbols.warning4.0"=FALSE) # not sure if this is necessary
options("getSymbols.yahoo.warning"=FALSE) # not sure if this is necessary
# Downloading Apple price using quantmod

getSymbols("PALL", from = '2015-01-01',
           to = "2017-01-01",warnings = FALSE,
           auto.assign = TRUE)
## [1] "PALL"
head(PALL)
##            PALL.Open PALL.High PALL.Low PALL.Close PALL.Volume PALL.Adjusted
## 2015-01-02     77.00     77.59    77.00      77.11       10300         77.11
## 2015-01-05     77.20     77.74    76.90      77.09       21900         77.09
## 2015-01-06     77.41     78.54    77.30      77.82       32600         77.82
## 2015-01-07     77.23     77.23    76.25      76.80       49700         76.80
## 2015-01-08     76.91     77.36    76.60      76.76       26400         76.76
## 2015-01-09     77.10     77.91    77.10      77.83       14200         77.83

This gives an “xts” object which can be plotted with chart_Series.

chart_Series(PALL)

We can also use this and just one column of data for a simpler plot.

pall_tq <- tq_get('PALL', from = '2015-01-01', to = "2017-01-01", get = "stock.prices" )
head(pall_tq)
## # A tibble: 6 × 8
##   symbol date        open  high   low close volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl>
## 1 PALL   2015-01-02  77    77.6  77    77.1  10300     77.1
## 2 PALL   2015-01-05  77.2  77.7  76.9  77.1  21900     77.1
## 3 PALL   2015-01-06  77.4  78.5  77.3  77.8  32600     77.8
## 4 PALL   2015-01-07  77.2  77.2  76.2  76.8  49700     76.8
## 5 PALL   2015-01-08  76.9  77.4  76.6  76.8  26400     76.8
## 6 PALL   2015-01-09  77.1  77.9  77.1  77.8  14200     77.8
pall_plot <- ggplot(pall_tq, aes(x=date, y = adjusted)) +
  geom_line()
pall_plot

This gives us a tibble dataframe.
Let’s try to add the PALL price to the other charts:

fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
fig3 <- ggplotly(comm_short_long_ratio)
fig4 <- ggplotly(pall_plot)
figs_1_2_3_4 <- subplot(fig1, fig2, fig3, fig4, nrows = 4, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis")
figs_1_2_3_4
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Clearly, that did not work. Maybe need to add palladium data to the other tibble dataframe.
Might be as issue with format. One has format “Date” and the other has format “POSIXct”.
That was the issue. Corrected below. Used:
https://www.statology.org/lubridate-convert-character-to-date/
https://lubridate.tidyverse.org/reference/as_date.html
We then used anti_join function to find rows of palladium_FUT15_16 that DO NOT have a match in pall_tq.
There were zero. That is good.
We then used semi_join function to find rows of palladium_FUT15_16 that DO have a match in pall_tq.
There were 104, which is every row in that tibble dataframe. That is good.
Used:
https://www.listendata.com/2016/08/dplyr-tutorial.html#join_function

# make a new tibble to use for now
palladium_FUT15_16_temp <- palladium_FUT15_16
library(lubridate) # to convert all to same date format
# rename column in palladium_FUT15_15 to match pall_tq
palladium_FUT15_16_temp <- rename(palladium_FUT15_16_temp, date=Report_Date_as_MM_DD_YYYY)
palladium_FUT15_16_temp$date <- ymd(palladium_FUT15_16_temp$date)

#palladium_FUT15_16 <- rename(palladium_FUT15_16, date=Date)
# find where join might work
#palladium_FUT15_16_with_price <- 
anti_join(palladium_FUT15_16_temp, pall_tq, by = "date")
## # A tibble: 0 × 128
## # ℹ 128 variables: Market_and_Exchange_Names <chr>,
## #   As_of_Date_In_Form_YYMMDD <chr>, date <date>,
## #   CFTC_Contract_Market_Code <chr>, CFTC_Market_Code <chr>,
## #   CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>, Open_Interest_All <dbl>,
## #   NonComm_Positions_Long_All <dbl>, NonComm_Positions_Short_All <dbl>,
## #   NonComm_Postions_Spread_All <dbl>, Comm_Positions_Long_All <dbl>,
## #   Comm_Positions_Short_All <dbl>, Tot_Rept_Positions_Long_All <dbl>, …
semi_join(palladium_FUT15_16_temp, pall_tq, by = "date")
## # A tibble: 104 × 128
##    Market_and_Exchange_Names                As_of_Date_In_Form_YYMMDD date      
##    <chr>                                    <chr>                     <date>    
##  1 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161227                    2016-12-27
##  2 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161220                    2016-12-20
##  3 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161213                    2016-12-13
##  4 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161206                    2016-12-06
##  5 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161129                    2016-11-29
##  6 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161122                    2016-11-22
##  7 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161115                    2016-11-15
##  8 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161108                    2016-11-08
##  9 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161101                    2016-11-01
## 10 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161025                    2016-10-25
## # ℹ 94 more rows
## # ℹ 125 more variables: CFTC_Contract_Market_Code <chr>,
## #   CFTC_Market_Code <chr>, CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>,
## #   Open_Interest_All <dbl>, NonComm_Positions_Long_All <dbl>,
## #   NonComm_Positions_Short_All <dbl>, NonComm_Postions_Spread_All <dbl>,
## #   Comm_Positions_Long_All <dbl>, Comm_Positions_Short_All <dbl>,
## #   Tot_Rept_Positions_Long_All <dbl>, Tot_Rept_Positions_Short_All <dbl>, …

Let’s add pall_tq to palladium_FUT15_16 to see if we can plot better.

palladium_FUT15_16_temp_2 <- left_join(palladium_FUT15_16_temp, pall_tq, by = "date")
palladium_FUT15_16_temp_2
## # A tibble: 104 × 135
##    Market_and_Exchange_Names                As_of_Date_In_Form_YYMMDD date      
##    <chr>                                    <chr>                     <date>    
##  1 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161227                    2016-12-27
##  2 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161220                    2016-12-20
##  3 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161213                    2016-12-13
##  4 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161206                    2016-12-06
##  5 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161129                    2016-11-29
##  6 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161122                    2016-11-22
##  7 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161115                    2016-11-15
##  8 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161108                    2016-11-08
##  9 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161101                    2016-11-01
## 10 PALLADIUM - NEW YORK MERCANTILE EXCHANGE 161025                    2016-10-25
## # ℹ 94 more rows
## # ℹ 132 more variables: CFTC_Contract_Market_Code <chr>,
## #   CFTC_Market_Code <chr>, CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>,
## #   Open_Interest_All <dbl>, NonComm_Positions_Long_All <dbl>,
## #   NonComm_Positions_Short_All <dbl>, NonComm_Postions_Spread_All <dbl>,
## #   Comm_Positions_Long_All <dbl>, Comm_Positions_Short_All <dbl>,
## #   Tot_Rept_Positions_Long_All <dbl>, Tot_Rept_Positions_Short_All <dbl>, …

Seems ok.
Let’s plot “adjusted” price. And with a ratio.

palladium_price <- ggplot(palladium_FUT15_16_temp_2)  +
  geom_line(aes(x=date,y=adjusted)) +
  labs(
    y="Ratio",
    x="Date",
    title="Price of PALL ETF"
  )
plot(palladium_price)

comm_short_long_ratio <- ggplot(palladium_FUT15_16)  +
  geom_line(aes(x=Report_Date_as_MM_DD_YYYY,y=short_long_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  )
plot(comm_short_long_ratio)

That works.
Now, back to putting them all together.

# Redo
# Make a plot with palladium data  
comm_long_short <- ggplot(palladium_FUT15_16_temp_2)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # add label
  labs(
    y="Commercial Interest",
    x="Date",
    title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  )


# Redo long short ratio
comm_long_short_ratio <- ggplot(palladium_FUT15_16_temp_2)  +
  geom_line(aes(x=date,y=long_short_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  )

# Redo short long ratio
comm_short_long_ratio <- ggplot(palladium_FUT15_16_temp_2)  +
  geom_line(aes(x=date,y=short_long_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  )


fig1 <- ggplotly(comm_long_short)
fig2 <- ggplotly(comm_long_short_ratio)
fig3 <- ggplotly(comm_short_long_ratio)
fig4 <- ggplotly(palladium_price)
figs_1_2_3_4 <- subplot(fig1, fig2, fig3, fig4, nrows = 4, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")

figs_1_2_3_4
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

That works better. Need to clean up titles and such.
https://plotly.com/r/subplots/.

annotations = list( 
  list( 
    x = 0.2,  
    y = 1.0,  
    text = "Plot 1",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.8,  
    y = 1,  
    text = "Plot 2",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.2,  
    y = 0.4,  
    text = "Plot 3",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),
  list( 
    x = 0.8,  
    y = 0.4,  
    text = "Plot 4",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

figs_1_2_3_4 <- figs_1_2_3_4 %>%layout(annotations = annotations) 
figs_1_2_3_4
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Got some stuff working. Now try to reproduce the original plot.

# Make a plot with palladium data  
comm_long_short_bar <- ggplot(palladium_FUT15_16_temp_2, aes(x = date))  +
  # line for Commercial Long
  geom_bar(aes(y=Comm_Positions_Long_All, colour = "Long"), stat = "identity") +
  # line for Commercial Short
  geom_bar(aes(y=Comm_Positions_Short_All, colour = "Short"), stat = "identity") +
  # better colors and legend
  scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # add label
  labs(
    y="Commercial Interest",
    x="Date",
    title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  )
# show plot. 
plot(comm_long_short_bar)

Both on same plot overlayed or something. Need side by side or above and below axis.
For ggplot2 and bar charts, it’s a bit more difficult. Need to rearrange data.
https://dk81.github.io/dkmathstats_site/rvisual-sidebyside-bar.html
http://www.sthda.com/english/wiki/ggplot2-barplots-quick-start-guide-r-software-and-data-visualization#google_vignette
https://r-graph-gallery.com/48-grouped-barplot-with-ggplot2
https://www.rpubs.com/dvdunne/ggplot_two_bars
https://stackoverflow.com/questions/42820677/ggplot-bar-plot-side-by-side-using-two-variables

# Need to rearrange data for bar plot for geom_bar
palladium_FUT15_16_temp_2_with_pivot <- palladium_FUT15_16_temp_2 %>% pivot_longer(cols = c('Comm_Positions_Long_All','Comm_Positions_Short_All'), names_to = "variable", values_to = "value")
# Make a plot with palladium data  
comm_long_short_bar <- ggplot(palladium_FUT15_16_temp_2_with_pivot, aes(x = date, y = value, fill=variable))  +
  # line for Commercial Long
  geom_bar(stat = "identity", position = "dodge")
  # line for Commercial Short
  # geom_bar(aes(y=Comm_Positions_Short_All, colour = "Short"), stat = "identity") +
  # # better colors and legend
  # scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # # add label
  # labs(
  #   y="Commercial Interest",
  #   x="Date",
  #   title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  #)
# show plot. 
plot(comm_long_short_bar)

Hmmm… this is something.
Make short interest negative:
need help here
https://forum.posit.co/t/mutate-with-case-when-and-replace/98315
https://dplyr.tidyverse.org/reference/case_when.html
https://www.tutorialspoint.com/how-to-display-negative-labels-below-bars-in-barplot-using-ggplot2-in-r
https://r-graph-gallery.com/341-stacked-barplot-with-negative-values.html

# Need to rearrange data for bar plot for geom_bar
palladium_FUT15_16_temp_2_with_pivot <- palladium_FUT15_16_temp_2_with_pivot %>%
  mutate(value = ifelse(variable =="Comm_Positions_Short_All", value * -1, value))

# Make a plot with palladium data  
comm_long_short_bar <- ggplot(palladium_FUT15_16_temp_2_with_pivot, aes(x = date, y = value, fill=variable))  +
  # line for Commercial Long
  geom_bar(stat = "identity", position = "dodge")
  # line for Commercial Short
  # geom_bar(aes(y=Comm_Positions_Short_All, colour = "Short"), stat = "identity") +
  # # better colors and legend
  # scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # # add label
  # labs(
  #   y="Commercial Interest",
  #   x="Date",
  #   title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  #)
# show plot. 
plot(comm_long_short_bar)

Now with plotly:

Multiple chart types like example:
https://plotly.com/r/graphing-multiple-chart-types/

Time series and financial data:
https://plotly.com/r/time-series/#hover-templates-with-mixtures-of-period-data

ggplotly(comm_long_short_bar)

That works.
Clean up colors and axis. Add trace for both.

fig1 <- ggplotly(comm_long_short_bar)
fig2 <- ggplotly(comm_long_short_ratio)
fig3 <- ggplotly(comm_short_long_ratio)
fig4 <- ggplotly(palladium_price)
figs_1_2_3_4 <- subplot(fig1, fig2, fig3, fig4, nrows = 4, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")

figs_1_2_3_4
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Try to max and min of next x rows for use for max gain and max loss in next xxx months.
Make new columns via mutate and take a look.
https://stackoverflow.com/questions/66049527/r-display-first-10-rows-of-data-of-certain-columns
slider library for getting max or min value in last xxx rows
https://cran.r-project.org/web/packages/slider/vignettes/slider.html
https://www.tidyverse.org/blog/2020/02/slider-0-1-0/
https://stackoverflow.com/questions/38405025/find-running-minimum-and-max-in-r
https://stackoverflow.com/questions/63632648/how-to-find-the-maximum-value-in-the-20-previous-rows-of-a-column-in-r

library(slider)
# for now using without pivot
palladium_FUT15_16_temp_2_max_and_min <- palladium_FUT15_16_temp_2 %>% 
  mutate(six_month_max = slide_dbl(adjusted, max, .before = 26, .complete = TRUE)) %>% 
  mutate(six_month_min = slide_dbl(adjusted, min, .before = 26, .complete = TRUE)) %>% 
  mutate(max_gain = 100*(six_month_max-adjusted)/adjusted) %>% 
  mutate(max_loss = 100*(six_month_min-adjusted)/adjusted)
head(palladium_FUT15_16_temp_2_max_and_min,20)[c("adjusted","six_month_max","six_month_min","max_gain","max_loss")]
## # A tibble: 20 × 5
##    adjusted six_month_max six_month_min max_gain max_loss
##       <dbl>         <dbl>         <dbl>    <dbl>    <dbl>
##  1     64.6            NA            NA       NA       NA
##  2     64.0            NA            NA       NA       NA
##  3     70.0            NA            NA       NA       NA
##  4     70.5            NA            NA       NA       NA
##  5     73.2            NA            NA       NA       NA
##  6     71.3            NA            NA       NA       NA
##  7     67.8            NA            NA       NA       NA
##  8     63.6            NA            NA       NA       NA
##  9     60.8            NA            NA       NA       NA
## 10     60.8            NA            NA       NA       NA
## 11     61.4            NA            NA       NA       NA
## 12     62.2            NA            NA       NA       NA
## 13     67.0            NA            NA       NA       NA
## 14     67.2            NA            NA       NA       NA
## 15     65.6            NA            NA       NA       NA
## 16     63.0            NA            NA       NA       NA
## 17     67.1            NA            NA       NA       NA
## 18     65.3            NA            NA       NA       NA
## 19     67.2            NA            NA       NA       NA
## 20     67.5            NA            NA       NA       NA

Let’s try to look at plots of max gain and loss against price and long/short ratios.

comm_long_short_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # add label
  labs(
    y="Commercial Interest",
    x="Date",
    title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  )


# Redo long short ratio
comm_long_short_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=long_short_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  )

# Redo short long ratio
comm_short_long_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=short_long_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  )



palladium_price_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=adjusted)) +
  labs(
    y="Ratio",
    x="Date",
    title="Price of PALL ETF"
  )
#plot(palladium_price)

max_gain_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_gain))
max_loss_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_loss))

fig1 <- ggplotly(comm_long_short_maxmin)
fig2 <- ggplotly(comm_long_short_ratio_maxmin)
fig3 <- ggplotly(comm_short_long_ratio_maxmin)
fig4 <- ggplotly(palladium_price_maxmin)
fig5 <- ggplotly(max_gain_maxmin)
fig6 <- ggplotly(max_loss_maxmin)

figs_1_2_3_4_5_5_maxmin <- subplot(fig1, fig2, fig3, fig4, fig5, fig6, nrows = 6, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")

figs_1_2_3_4_5_5_maxmin
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

You can always zoom in plotly by selecting a range right on the plot.

add a rangeslider for date
https://plotly-r.com/animating-views
https://plotly.com/r/range-slider/
https://plotly.com/r/reference/layout/sliders/#layout-sliders
https://stackoverflow.com/questions/70943105/how-to-dynamically-change-plotly-axis-based-on-crosstalk-conditions/
https://plot.ly/r/sliders/

comm_long_short_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(name = "Commercial Interest", values = c("Short" = "red", "Long" = "darkgreen")) +
  # add label
  labs(
    y="Commercial Interest",
    x="Date",
    title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  )


# Redo long short ratio
comm_long_short_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=long_short_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  )

# Redo short long ratio
comm_short_long_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=short_long_ratio)) +
  labs(
    y="Ratio",
    x="Date",
    title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  )



palladium_price_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=adjusted)) +
  labs(
    y="Ratio",
    x="Date",
    title="Price of PALL ETF"
  )
#plot(palladium_price)

max_gain_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_gain))
max_loss_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_loss))

fig1 <- ggplotly(comm_long_short_maxmin) %>% layout(yaxis = list(title = "yaxis test tile"))
fig2 <- ggplotly(comm_long_short_ratio_maxmin)
fig3 <- ggplotly(comm_short_long_ratio_maxmin)
fig4 <- ggplotly(palladium_price_maxmin)
fig5 <- ggplotly(max_gain_maxmin)
fig6 <- ggplotly(max_loss_maxmin)

figs_1_2_3_4_5_5_maxmin <- subplot(fig1, fig2, fig3, fig4, fig5, fig6, nrows = 6, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", xaxis = list(
    rangeslider = list(type = "date")))

figs_1_2_3_4_5_5_maxmin
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'
# layout(
#   xaxis = list(
#     rangeslider = list(type = "Report_Date_as_MM_DD_YYY")))

This works.
#### The plots at the range slider are all supposed to be there.

Now update sizes/heights and add y axis titles.
https://plotly-r.com/arranging-views
https://plotly.com/r/subplots/

Having some issues with getting plot to look how it should

Trying some dummy data first

Make three tibbles and combine like you need to do for the data above.

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max
## # A tibble: 4 × 3
##   date_temp comm_long_temp ratio1_temp
##       <dbl>          <dbl>       <dbl>
## 1         3           1000         110
## 2         4           1100         120
## 3         5           1200          NA
## 4         2             NA         100
df_max <- full_join(df_max, df3, by = "date_temp")
df_max
## # A tibble: 6 × 4
##   date_temp comm_long_temp ratio1_temp ratio2_temp
##       <dbl>          <dbl>       <dbl>       <dbl>
## 1         3           1000         110          NA
## 2         4           1100         120          NA
## 3         5           1200          NA          NA
## 4         2             NA         100          12
## 5         0             NA          NA          10
## 6         1             NA          NA          11

We now have a tibble which is all “linked” by date_temp.
Make plots.

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp))
plot(p1)
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_line()`).

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp))
plot(p2)
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_line()`).

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp))
plot(p3)
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_line()`).

Now make three plotly plots.

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp))
#plot(p1)
p1 <- ggplotly(p1)
p1
p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp))
#plot(p2)
p2 <- ggplotly(p2)
p2
p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp))
#plot(p3)
p3 <- ggplotly(p3)
p3

Now make subplots on one x axis with same hover line across all plots.

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp))
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp))
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp))
#plot(p3)
p3 <- ggplotly(p3)
#p3

# combine on one chart with shared X axis
fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")
fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Figure out a legend.
https://ggplot2.tidyverse.org/reference/guide_legend.html
https://stackoverflow.com/questions/74392543/how-to-add-a-legend-to-ggplot-in-r
https://r-charts.com/ggplot2/legend/
https://www.tidyverse.org/blog/2024/02/ggplot2-3-5-0-legends/
https://r-graph-gallery.com/239-custom-layout-legend-ggplot2.html
http://www.sthda.com/english/wiki/ggplot2-legend-easy-steps-to-change-the-position-and-the-appearance-of-a-graph-legend-in-r-software

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "comm_long_temp"))
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "ratio1_temp"))
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "ratio2_temp"))
#plot(p3)
p3 <- ggplotly(p3)
#p3

# combine on one chart with shared X axis
fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")
fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

change name of legend

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "comm_long_temp")) + 
  scale_color_manual(values = "red") +
  labs(colour = "test")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "ratio1_temp")) +
  scale_color_manual(values = "green") +
  labs(colour = "test")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "ratio2_temp")) +
  scale_color_manual(values = "blue") +
  labs(colour = "test")
#plot(p3)
p3 <- ggplotly(p3)
#p3

# combine on one chart with shared X axis
fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")
fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

change name of individual lines

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  scale_color_manual(values = "red") +
  labs(colour = "Commercials")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  scale_color_manual(values = "green") +
  labs(colour = "Commercials")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials")
#plot(p3)
p3 <- ggplotly(p3)
#p3

# combine on one chart with shared X axis
fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")
fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

add points and those colors.
http://www.sthda.com/english/wiki/ggplot2-line-plot-quick-start-guide-r-software-and-data-visualization
https://www.appsilon.com/post/ggplot2-line-charts
https://stackoverflow.com/questions/27350243/ggplot-line-graph-with-different-line-styles-and-markers
https://stackoverflow.com/questions/31069324/adding-points-from-other-dataset-to-ggplot2

# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  geom_point(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  scale_color_manual(values = "red") +
  labs(colour = "Commercials")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  geom_point(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  scale_color_manual(values = "green") +
  labs(colour = "Commercials")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  geom_point(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials")
#plot(p3)
p3 <- ggplotly(p3)
#p3

# combine on one chart with shared X axis
fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium")
fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

now add y axis labels.
and change x axis label

library(gridExtra)
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  # geom_point(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  # scale_color_manual(values = "red") +
  # labs(colour = "Commercials", x="Date", y="Ratio")
  xlab("p1x") + ylab("p1y")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  # geom_point(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  # scale_color_manual(values = "green") +
  # #labs(colour = "Commercials", x="Date", y="Ratio")
  # xlab("sdfs") + ylab("asdfsadf")
  xlab("p2x") + ylab("p2y")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  # geom_point(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  # scale_color_manual(values = "blue") +
  # labs(colour = "Commercials", x="Date", y="Ratio")
  xlab("p3x") + ylab("p3y")
#plot(p3)
p3 <- ggplotly(p3) #%>% 
  #layout(xaxis = list(title = "Date"), yaxis = list(title = "Contracts"))
#p3

# combine on one chart with shared X axis
# fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis",  titleY = TRUE, titleX = TRUE, margin = 0.05)
fig_temp <- subplot(p1, p2, p3, nrows = 3,   titleY = TRUE, titleX = TRUE, margin = 0.05)
annotations = list( 
  list( 
    x = 0.2,  
    y = 1.0,  
    text = "Plot 1",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.8,  
    y = 1,  
    text = "Plot 2",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.2,  
    y = 0.4,  
    text = "Plot 3",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

#fig_temp <- fig_temp %>%layout(annotations = annotations) 
#fig

fig_temp

The issue is Share X trying to make axis labels show up.

library(ggplot2)
library(gridExtra)
library(plotly)

d <- data.frame(x=1:20,y=1:20, z=20:1)
p1 <- ggplot(data=d) +
  geom_point(aes(x=x, y=y)) +
  xlab("X") + ylab("Y")
p2 <- ggplot(data=d) +
  geom_point(aes(x=x, y=z)) +
  xlab("X") + ylab("Z")

ply1 <- ggplotly(p1)
ply2 <- ggplotly(p2)
ply_total <- subplot(ply1, ply2, nrows=1, 
        titleY = TRUE, 
        titleX = TRUE,
        margin = 0.05)
ply_total <- ply_total %>%  layout(autosize = F, width = 500, height = 500)
## Warning: Specifying width/height in layout() is now deprecated.
## Please specify in ggplotly() or plot_ly()
ply_total

https://github.com/plotly/plotly.R/issues/1415
https://stackoverflow.com/questions/75132414/axis-labels-lost-in-plotlysubplot
https://stackoverflow.com/questions/61553282/how-to-correctly-place-axis-labels-in-plotly-r-subplots-with-multiple-axes
https://community.plotly.com/t/subplot-y-axis-names/2683

library(gridExtra)
# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  # geom_point(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  # scale_color_manual(values = "red") +
  # labs(colour = "Commercials", x="Date", y="Ratio")
  xlab("p1x") + ylab("p1y")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  # geom_point(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  # scale_color_manual(values = "green") +
  # #labs(colour = "Commercials", x="Date", y="Ratio")
  # xlab("sdfs") + ylab("asdfsadf")
  xlab("p2x") + ylab("p2y")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  # geom_point(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  # scale_color_manual(values = "blue") +
  # labs(colour = "Commercials", x="Date", y="Ratio")
  xlab("p3x") + ylab("p3y")
#plot(p3)
p3 <- ggplotly(p3) #%>% 
  #layout(xaxis = list(title = "Date"), yaxis = list(title = "Contracts"))
#p3

# combine on one chart with shared X axis
# fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis",  titleY = TRUE, titleX = TRUE, margin = 0.05)
fig_temp <- subplot(p1, p2, p3, nrows = 3,   titleY = TRUE, shareX = TRUE, margin = 0.05) %>% layout(hovermode = "x unified", hoversubplots = "axis")
annotations = list( 
  list( 
    x = 0.2,  
    y = 1.0,  
    text = "Plot 1",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.8,  
    y = 1,  
    text = "Plot 2",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.2,  
    y = 0.4,  
    text = "Plot 3",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

#fig_temp <- fig_temp %>%layout(annotations = annotations) 
#fig

fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Ok, this might work.
Need to figure out rangeslider too.

library(gridExtra)
# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  # geom_point(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  # scale_color_manual(values = "red") +
  # labs(colour = "Commercials", x="Date", y="Ratio")
  xlab("p1x") + ylab("p1y")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  # geom_point(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  # scale_color_manual(values = "green") +
  # #labs(colour = "Commercials", x="Date", y="Ratio")
  # xlab("sdfs") + ylab("asdfsadf")
  xlab("p2x") + ylab("p2y")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  # geom_point(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  # scale_color_manual(values = "blue") +
  # labs(colour = "Commercials", x="Date", y="Ratio")
  xlab("p3x") + ylab("p3y")
#plot(p3)
p3 <- ggplotly(p3) #%>% 
  #layout(xaxis = list(title = "Date"), yaxis = list(title = "Contracts"))
#p3

# combine on one chart with shared X axis
# fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis",  titleY = TRUE, titleX = TRUE, margin = 0.05)
fig_temp <- subplot(p1, p2, p3, nrows = 3,   titleY = TRUE, shareX = TRUE, margin = 0.05) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", xaxis = list(
    rangeslider = list(type = "date")))
annotations = list( 
  list( 
    x = 0.2,  
    y = 1.0,  
    text = "Plot 1",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.8,  
    y = 1,  
    text = "Plot 2",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.2,  
    y = 0.4,  
    text = "Plot 3",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

#fig_temp <- fig_temp %>%layout(annotations = annotations) 
#fig

fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Now, back with all the colors before:

library(gridExtra)
# Make three dummy tibbles
df1 <- data.frame(date_temp = c(3, 4, 5), comm_long_temp = c(1000, 1100, 1200))
df1 <- as_tibble(df1)
df2 <- data.frame(date_temp = c(2, 3, 4), ratio1_temp = c(100, 110, 120))
df2 <- as_tibble(df2)
df3 <- data.frame(date_temp = c(0, 1, 2), ratio2_temp = c(10, 11, 12))
df3 <- as_tibble(df3)

# join into one tibble
df_max <- full_join(df1, df2, by = "date_temp")
df_max <- full_join(df_max, df3, by = "date_temp")

# make 3 plotly plots
p1 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  geom_point(aes(x = date_temp, y = comm_long_temp, colour = "Commercial Long COT")) +
  scale_color_manual(values = "red") +
  labs(colour = "Commercials") +
  xlab("p1x") + ylab("p1y")
#plot(p1)
p1 <- ggplotly(p1)
#p1

p2 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  geom_point(aes(x = date_temp, y = ratio1_temp, colour = "Commercial Ratio Long")) +
  scale_color_manual(values = "green") +
  labs(colour = "Commercials") +
  # xlab("sdfs") + ylab("asdfsadf")
  xlab("p2x") + ylab("p2y")
#plot(p2)
p2 <- ggplotly(p2)
#p2

p3 <- ggplot(df_max) +
  geom_line(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  geom_point(aes(x = date_temp, y = ratio2_temp, colour = "Commercial Ratio Short")) +
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials") +
  xlab("p3x") + ylab("p3y")
#plot(p3)
p3 <- ggplotly(p3) #%>% 
  #layout(xaxis = list(title = "Date"), yaxis = list(title = "Contracts"))
#p3

# combine on one chart with shared X axis
# fig_temp <- subplot(p1, p2, p3, nrows = 3, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis",  titleY = TRUE, titleX = TRUE, margin = 0.05)
fig_temp <- subplot(p1, p2, p3, nrows = 3,   titleY = TRUE, shareX = TRUE, margin = 0.05) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", xaxis = list(
    rangeslider = list(type = "date")))
annotations = list( 
  list( 
    x = 0.3,  
    y = 1.0,  
    text = "Plot 1",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.3,  
    y = 0.6,  
    text = "Plot 2",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ),  
  list( 
    x = 0.3,  
    y = 0.3,  
    text = "Plot 3",  
    xref = "paper",  
    yref = "paper",  
    xanchor = "center",  
    yanchor = "bottom",  
    showarrow = FALSE 
  ))

fig_temp <- fig_temp %>%layout(annotations = annotations) 
#fig

fig_temp
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

Ok, back to Palladium:
https://github.com/plotly/plotly.R/issues/1415

comm_long_short_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(values = c("Short" = "red", "Long" = "darkgreen")) +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Contracts")
  # add label
  # labs(
  #   y="Commercial Interest",
  #   x="Date",
  #   title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  # )


# Redo long short ratio
comm_long_short_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=long_short_ratio, colour = "Long Short Ratio")) + 
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  # )

# Redo short long ratio
comm_short_long_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=short_long_ratio, colour = "Short Long Ratio")) +
  scale_color_manual(values = "purple") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  # )



palladium_price_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=adjusted, colour = "Price")) +
  scale_color_manual(values = "orange") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Dollars")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Price of PALL ETF"
  # )
#plot(palladium_price)

max_gain_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_gain, colour = "Max Gain")) +
  scale_color_manual(values = "yellow") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

max_loss_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_loss, colour = "Max Loss")) +
  scale_color_manual(values = "brown") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

fig1 <- ggplotly(comm_long_short_maxmin) #%>% layout(yaxis = list(title = "yaxis test tile"))
fig2 <- ggplotly(comm_long_short_ratio_maxmin)
fig3 <- ggplotly(comm_short_long_ratio_maxmin)
fig4 <- ggplotly(palladium_price_maxmin)
fig5 <- ggplotly(max_gain_maxmin)
fig6 <- ggplotly(max_loss_maxmin)



figs_1_2_3_4_5_5_maxmin <- subplot(fig1, fig2, fig3, fig4, fig5, fig6, nrows = 6, titleY = TRUE, shareX = TRUE, margin = 0.05) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", xaxis = list(
    rangeslider = list(type = "date")))

figs_1_2_3_4_5_5_maxmin
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'

now make bigger?

comm_long_short_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(values = c("Short" = "red", "Long" = "darkgreen")) +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Contracts")
  # add label
  # labs(
  #   y="Commercial Interest",
  #   x="Date",
  #   title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  # )


# Redo long short ratio
comm_long_short_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=long_short_ratio, colour = "Long Short Ratio")) + 
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  # )

# Redo short long ratio
comm_short_long_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=short_long_ratio, colour = "Short Long Ratio")) +
  scale_color_manual(values = "purple") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  # )



palladium_price_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=adjusted, colour = "Price")) +
  scale_color_manual(values = "orange") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Dollars")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Price of PALL ETF"
  # )
#plot(palladium_price)

max_gain_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_gain, colour = "Max Gain")) +
  scale_color_manual(values = "yellow") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

max_loss_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_loss, colour = "Max Loss")) +
  scale_color_manual(values = "brown") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

fig1 <- ggplotly(comm_long_short_maxmin) #%>% layout(yaxis = list(title = "yaxis test tile"))
fig2 <- ggplotly(comm_long_short_ratio_maxmin)
fig3 <- ggplotly(comm_short_long_ratio_maxmin)
fig4 <- ggplotly(palladium_price_maxmin)
fig5 <- ggplotly(max_gain_maxmin)
fig6 <- ggplotly(max_loss_maxmin)


# remove margin for less space in between
figs_1_2_3_4_5_5_maxmin <- subplot(fig1, fig2, fig3, fig4, fig5, fig6, nrows = 6, titleY = TRUE, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", xaxis = list(
    rangeslider = list(type = "date")), autosize = F, width = 1000, height = 1000)
## Warning: Specifying width/height in layout() is now deprecated.
## Please specify in ggplotly() or plot_ly()
figs_1_2_3_4_5_5_maxmin
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'






























## now add range buttons for last xx months, xx years, all time
https://plotly.com/r/range-slider/
https://stackoverflow.com/questions/59877688/r-plotly-rangeselector-autoselect-1w
Might now work with ggplot2 and plotly https://community.plotly.com/t/rangeselector-buttons-with-plot-ly-vs-ggplotly/1562
can’t make it work yet

but maybe dynamic tricks???
https://github.com/plotly/plotly.R/issues/646

comm_long_short_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(values = c("Short" = "red", "Long" = "darkgreen")) +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Contracts")

# Redo long short ratio
comm_long_short_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=long_short_ratio, colour = "Long Short Ratio")) + 
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")

# Redo short long ratio
comm_short_long_ratio_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=short_long_ratio, colour = "Short Long Ratio")) +
  scale_color_manual(values = "purple") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")

palladium_price_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=adjusted, colour = "Price")) +
  scale_color_manual(values = "orange") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Dollars")

max_gain_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_gain, colour = "Max Gain")) +
  scale_color_manual(values = "magenta") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

max_loss_maxmin <- ggplot(palladium_FUT15_16_temp_2_max_and_min)  +
  geom_line(aes(x=date,y=max_loss, colour = "Max Loss")) +
  scale_color_manual(values = "brown") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

fig1 <- ggplotly(comm_long_short_maxmin) #%>% layout(yaxis = list(title = "yaxis test tile"))
fig2 <- ggplotly(comm_long_short_ratio_maxmin)
fig3 <- ggplotly(comm_short_long_ratio_maxmin)
fig4 <- ggplotly(palladium_price_maxmin)
fig5 <- ggplotly(max_gain_maxmin)
fig6 <- ggplotly(max_loss_maxmin)


# remove margin for less space in between
figs_1_2_3_4_5_5_maxmin <- subplot(fig1, fig2, fig3, fig4, fig5, fig6, nrows = 6, titleY = TRUE, shareX = TRUE) %>%
  layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", 
    xaxis = list(
      rangeselector = list(
        buttons = list(
          list(
            count = 3,
            label = "3 mo",
            step = "month",
            stepmode = "backward"),
          list(
            count = 6,
            label = "6 mo",
            step = "month",
            stepmode = "backward"),
          list(
            count = 1,
            label = "1 yr",
            step = "year",
            stepmode = "backward"),
          list(
            count = 1,
            label = "YTD",
            step = "year",
            stepmode = "todate"),
          list(step = "all"))),
      
    rangeslider = list(type = "date")), autosize = F, width = 1000, height = 1000)
## Warning: Specifying width/height in layout() is now deprecated.
## Please specify in ggplotly() or plot_ly()
figs_1_2_3_4_5_5_maxmin
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'






























now add all years of palladium data

# GET ALL DATA FROM ALL YEARS FOR PALL
# work with Palladium
# Use .csv files
palladium_FUT86_06 <- read_xls("FUT86_06.xls")
#palladium_FUT86_06
palladium_FUT86_06 <- palladium_FUT86_06 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))
#palladium_FUT86_06
# second column "As_of...." is in character form.  Need number to rbind with others
palladium_FUT86_06 <- palladium_FUT86_06 %>% mutate(As_of_Date_In_Form_YYMMDD = parse_number(As_of_Date_In_Form_YYMMDD))
#palladium_FUT86_06


palladium_FUT07_14 <- read_xls("FUT07_14.xls")
#palladium_FUT07_14
palladium_FUT07_14 <- palladium_FUT07_14 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))
# second column "As_of...." is in character form.  Need number to rbind with others
palladium_FUT07_14 <- palladium_FUT07_14 %>% mutate(As_of_Date_In_Form_YYMMDD = parse_number(As_of_Date_In_Form_YYMMDD))
#palladium_FUT07_14


palladium_FUT15_16 <- read_xls("FUT15_16.xls")
#palladium_FUT15_16
palladium_FUT15_16 <- palladium_FUT15_16 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))
#palladium_FUT15_16
# second column "As_of...." is in character form.  Need number to rbind with others
palladium_FUT15_16 <- palladium_FUT15_16 %>% mutate(As_of_Date_In_Form_YYMMDD = parse_number(As_of_Date_In_Form_YYMMDD))
#palladium_FUT15_16

palladium_FUT17 <- read_xls("FUT17.xls")
#palladium_FUT17
palladium_FUT17 <- palladium_FUT17 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT18 <- read_xls("FUT18.xls")
#palladium_FUT18
palladium_FUT18 <- palladium_FUT18 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT19 <- read_xls("FUT19.xls")
#palladium_FUT19
palladium_FUT19 <- palladium_FUT19 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT20 <- read_xls("FUT20.xls")
#palladium_FUT20
palladium_FUT20 <- palladium_FUT20 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT21 <- read_xls("FUT21.xls")
#palladium_FUT21
palladium_FUT21 <- palladium_FUT21 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT22 <- read_xls("FUT22.xls")
#palladium_FUT22
palladium_FUT22 <- palladium_FUT22 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT23 <- read_xls("FUT23.xls")
#palladium_FUT23
palladium_FUT23 <- palladium_FUT23 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_FUT24 <- read_xls("FUT24.xls")
#palladium_FUT24
palladium_FUT24 <- palladium_FUT24 %>% filter(str_detect( Market_and_Exchange_Names, "PALL"))

palladium_all <- bind_rows(palladium_FUT24, palladium_FUT23, palladium_FUT22, palladium_FUT21, palladium_FUT20, palladium_FUT19, palladium_FUT18, palladium_FUT17, palladium_FUT15_16, palladium_FUT07_14, palladium_FUT86_06)
# one file has double and one has character for date
# fixed above

palladium_all <- palladium_all %>% mutate(long_short_ratio = Comm_Positions_Long_All/Comm_Positions_Short_All)
palladium_all <- palladium_all %>% mutate(short_long_ratio = Comm_Positions_Short_All/Comm_Positions_Long_All)





# get all PALL prices
# tq_get from tidyquant returns a tibble
# PALL_price <- tq_get('PALL', from = '2000-01-01', to = "2025-01-01", get = "stock.prices" )
# head(PALL_price)
# PALL doesn't start until the first week of 2010
# leaving out the end date gets up to current data
# leaving out the start date only begins in 2014 for some reason
# look into this
PALL_price <- tq_get('PALL', from = '2000-01-01', get = "stock.prices")
head(PALL_price)
## # A tibble: 6 × 8
##   symbol date        open  high   low close  volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>   <dbl>    <dbl>
## 1 PALL   2010-01-08  43.7  45    43.2  43.2  294900     43.2
## 2 PALL   2010-01-11  43.7  43.7  43.2  43.7  338800     43.7
## 3 PALL   2010-01-12  43.6  43.8  42.3  42.3  340900     42.3
## 4 PALL   2010-01-13  42.4  42.7  41.7  42.7 1011400     42.7
## 5 PALL   2010-01-14  43.9  45.0  43.9  44.8  364600     44.8
## 6 PALL   2010-01-15  45.2  45.8  44.4  45.8  442300     45.8
tail(PALL_price)
## # A tibble: 6 × 8
##   symbol date        open  high   low close volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl>
## 1 PALL   2024-09-27  94.7  96.0  92.8  92.9 131300     92.9
## 2 PALL   2024-09-30  91.5  92.2  90.1  91.7 112300     91.7
## 3 PALL   2024-10-01  91.7  92.9  90.6  92.2  69500     92.2
## 4 PALL   2024-10-02  94.1  94.1  92.6  93.9  82200     93.9
## 5 PALL   2024-10-03  90.9  92.3  90.4  92.2  78400     92.2
## 6 PALL   2024-10-04  92.4  93.3  91.4  93   197000     93
# need to combine PALL_price and palladium_all
library(lubridate)
# rename column in palladium_FUT15_15 to match pall_tq
palladium_all <- rename(palladium_all, date=Report_Date_as_MM_DD_YYYY)
# make sure in ymd format
palladium_all$date <- ymd(palladium_all$date)


# find where join might work
#palladium_FUT15_16_with_price <- 
anti_join(palladium_all, PALL_price, by = "date")
## # A tibble: 990 × 128
##    Market_and_Exchange_Names                As_of_Date_In_Form_YYMMDD date      
##    <chr>                                                        <dbl> <date>    
##  1 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    121030 2012-10-30
##  2 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    100105 2010-01-05
##  3 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91229 2009-12-29
##  4 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91222 2009-12-22
##  5 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91215 2009-12-15
##  6 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91208 2009-12-08
##  7 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91201 2009-12-01
##  8 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91124 2009-11-24
##  9 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91117 2009-11-17
## 10 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                     91109 2009-11-09
## # ℹ 980 more rows
## # ℹ 125 more variables: CFTC_Contract_Market_Code <chr>,
## #   CFTC_Market_Code <chr>, CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>,
## #   Open_Interest_All <dbl>, NonComm_Positions_Long_All <dbl>,
## #   NonComm_Positions_Short_All <dbl>, NonComm_Postions_Spread_All <dbl>,
## #   Comm_Positions_Long_All <dbl>, Comm_Positions_Short_All <dbl>,
## #   Tot_Rept_Positions_Long_All <dbl>, Tot_Rept_Positions_Short_All <dbl>, …
semi_join(palladium_all, PALL_price, by = "date")
## # A tibble: 763 × 128
##    Market_and_Exchange_Names                As_of_Date_In_Form_YYMMDD date      
##    <chr>                                                        <dbl> <date>    
##  1 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240827 2024-08-27
##  2 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240820 2024-08-20
##  3 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240813 2024-08-13
##  4 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240806 2024-08-06
##  5 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240730 2024-07-30
##  6 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240723 2024-07-23
##  7 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240716 2024-07-16
##  8 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240709 2024-07-09
##  9 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240702 2024-07-02
## 10 PALLADIUM - NEW YORK MERCANTILE EXCHANGE                    240625 2024-06-25
## # ℹ 753 more rows
## # ℹ 125 more variables: CFTC_Contract_Market_Code <chr>,
## #   CFTC_Market_Code <chr>, CFTC_Region_Code <chr>, CFTC_Commodity_Code <chr>,
## #   Open_Interest_All <dbl>, NonComm_Positions_Long_All <dbl>,
## #   NonComm_Positions_Short_All <dbl>, NonComm_Postions_Spread_All <dbl>,
## #   Comm_Positions_Long_All <dbl>, Comm_Positions_Short_All <dbl>,
## #   Tot_Rept_Positions_Long_All <dbl>, Tot_Rept_Positions_Short_All <dbl>, …
palladium_all <- left_join(palladium_all, PALL_price, by = "date")

head(palladium_all$adjusted)
## [1] 89.20 85.00 85.90 80.34 82.00 85.31
tail(palladium_all$adjusted)
## [1] NA NA NA NA NA NA
# now add max and min
library(slider)
# for now using without pivot
palladium_all <- palladium_all %>% 
  mutate(six_month_max = slide_dbl(adjusted, max, .before = 26, .complete = TRUE)) %>% 
  mutate(six_month_min = slide_dbl(adjusted, min, .before = 26, .complete = TRUE)) %>% 
  mutate(max_gain = 100*(six_month_max-adjusted)/adjusted) %>% 
  mutate(max_loss = 100*(six_month_min-adjusted)/adjusted)
head(palladium_all,20)[c("adjusted","six_month_max","six_month_min","max_gain","max_loss")]
## # A tibble: 20 × 5
##    adjusted six_month_max six_month_min max_gain max_loss
##       <dbl>         <dbl>         <dbl>    <dbl>    <dbl>
##  1     89.2            NA            NA       NA       NA
##  2     85              NA            NA       NA       NA
##  3     85.9            NA            NA       NA       NA
##  4     80.3            NA            NA       NA       NA
##  5     82              NA            NA       NA       NA
##  6     85.3            NA            NA       NA       NA
##  7     88.5            NA            NA       NA       NA
##  8     90.0            NA            NA       NA       NA
##  9     93.3            NA            NA       NA       NA
## 10     86.7            NA            NA       NA       NA
## 11     81.8            NA            NA       NA       NA
## 12     81.7            NA            NA       NA       NA
## 13     84.1            NA            NA       NA       NA
## 14     90.2            NA            NA       NA       NA
## 15     94.8            NA            NA       NA       NA
## 16     90.0            NA            NA       NA       NA
## 17     89.3            NA            NA       NA       NA
## 18     87.8            NA            NA       NA       NA
## 19     93.7            NA            NA       NA       NA
## 20     93.3            NA            NA       NA       NA
tail(palladium_all,20)[c("adjusted","six_month_max","six_month_min","max_gain","max_loss")]
## # A tibble: 20 × 5
##    adjusted six_month_max six_month_min max_gain max_loss
##       <dbl>         <dbl>         <dbl>    <dbl>    <dbl>
##  1       NA            NA            NA       NA       NA
##  2       NA            NA            NA       NA       NA
##  3       NA            NA            NA       NA       NA
##  4       NA            NA            NA       NA       NA
##  5       NA            NA            NA       NA       NA
##  6       NA            NA            NA       NA       NA
##  7       NA            NA            NA       NA       NA
##  8       NA            NA            NA       NA       NA
##  9       NA            NA            NA       NA       NA
## 10       NA            NA            NA       NA       NA
## 11       NA            NA            NA       NA       NA
## 12       NA            NA            NA       NA       NA
## 13       NA            NA            NA       NA       NA
## 14       NA            NA            NA       NA       NA
## 15       NA            NA            NA       NA       NA
## 16       NA            NA            NA       NA       NA
## 17       NA            NA            NA       NA       NA
## 18       NA            NA            NA       NA       NA
## 19       NA            NA            NA       NA       NA
## 20       NA            NA            NA       NA       NA
comm_long_short_maxmin <- ggplot(palladium_all)  +
  # line for Commercial Long
  geom_line(aes(x=date,y=Comm_Positions_Long_All, colour = "Long"), size = 1) +
  # line for Commercial Short
  geom_line(aes(x=date,y=Comm_Positions_Short_All*-1, colour = "Short"), size = 1) +
  # better colors and legend
  scale_color_manual(values = c("Short" = "red", "Long" = "darkgreen")) +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Contracts")
  # add label
  # labs(
  #   y="Commercial Interest",
  #   x="Date",
  #   title = "Commercial Futures Interest for Palladium As Reported by cftc.gov"
  # )


# Redo long short ratio
comm_long_short_ratio_maxmin <- ggplot(palladium_all)  +
  geom_line(aes(x=date,y=long_short_ratio, colour = "Long Short Ratio")) + 
  scale_color_manual(values = "blue") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Ratio of Commercial Long Interest to Commercial Short Interest - Palladium Futures"
  # )

# Redo short long ratio
comm_short_long_ratio_maxmin <- ggplot(palladium_all)  +
  geom_line(aes(x=date,y=short_long_ratio, colour = "Short Long Ratio")) +
  scale_color_manual(values = "purple") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Ratio")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Ratio of Commercial Short Interest to Commercial Long Interest - Palladium Futures"
  # )



palladium_price_maxmin <- ggplot(palladium_all)  +
  geom_line(aes(x=date,y=adjusted, colour = "Price - PALL ETF")) +
  scale_color_manual(values = "orange") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Dollars")
  # labs(
  #   y="Ratio",
  #   x="Date",
  #   title="Price of PALL ETF"
  # )
#plot(palladium_price)

max_gain_maxmin <- ggplot(palladium_all)  +
  geom_line(aes(x=date,y=max_gain, colour = "Max Gain - 6 months")) +
  scale_color_manual(values = "magenta") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

max_loss_maxmin <- ggplot(palladium_all)  +
  geom_line(aes(x=date,y=max_loss, colour = "Max Loss - 6 months")) +
  scale_color_manual(values = "brown") +
  labs(colour = "Commercials") +
  xlab("Date") + ylab("Percent")

fig1 <- ggplotly(comm_long_short_maxmin) #%>% layout(yaxis = list(title = "yaxis test tile"))
fig2 <- ggplotly(comm_long_short_ratio_maxmin)
fig3 <- ggplotly(comm_short_long_ratio_maxmin)
fig4 <- ggplotly(palladium_price_maxmin)
fig5 <- ggplotly(max_gain_maxmin)
fig6 <- ggplotly(max_loss_maxmin)


# remove margin for less space in between
figs_1_2_3_4_5_5_maxmin <- subplot(fig1, fig2, fig3, fig4, fig5, fig6, nrows = 6, titleY = TRUE, shareX = TRUE) %>% layout(hovermode = "x unified", hoversubplots = "axis", title = "Palladium", xaxis = list(
    rangeslider = list(type = "date")), autosize = F, width = 1000, height = 1000)
## Warning: Specifying width/height in layout() is now deprecated.
## Please specify in ggplotly() or plot_ly()
## Warning: Specifying width/height in layout() is now deprecated.
## Please specify in ggplotly() or plot_ly()
figs_1_2_3_4_5_5_maxmin
## Warning: 'layout' objects don't have these attributes: 'hoversubplots'
## Valid attributes include:
## '_deprecated', 'activeshape', 'annotations', 'autosize', 'autotypenumbers', 'calendar', 'clickmode', 'coloraxis', 'colorscale', 'colorway', 'computed', 'datarevision', 'dragmode', 'editrevision', 'editType', 'font', 'geo', 'grid', 'height', 'hidesources', 'hoverdistance', 'hoverlabel', 'hovermode', 'images', 'legend', 'mapbox', 'margin', 'meta', 'metasrc', 'modebar', 'newshape', 'paper_bgcolor', 'plot_bgcolor', 'polar', 'scene', 'selectdirection', 'selectionrevision', 'separators', 'shapes', 'showlegend', 'sliders', 'smith', 'spikedistance', 'template', 'ternary', 'title', 'transition', 'uirevision', 'uniformtext', 'updatemenus', 'width', 'xaxis', 'yaxis', 'barmode', 'bargap', 'mapType'






























add bar plot with long and short against each other

add 12 months max gain and loss

add amount of interest across all

add non-commercials

add percentile for long and short interest and ratios

plotly may be able to do dual axes
https://plotly.com/r/multiple-axes/ Plotly stuff:

Try figuring stacking with the same axis

SHINY!

https://plotly-r.com