joshuaulrich / quantmod

Quantitative Financial Modelling Framework
http://www.quantmod.com/
GNU General Public License v3.0
794 stars 219 forks source link

Add cryptocurrency market data to Quantmod #410

Closed serkor1 closed 4 months ago

serkor1 commented 4 months ago

Description

I am the maintainer of the cryptoQuotes-package, and the main functionality of the package could be easily integrated into quantmod as it has been developed to work directly with it, and TTR.

What I could do is to wrap the main function, which extracts OHLC data, into some function foo which behaves as quantmod::getSymbols() and has the same arguments.

Expected behavior

Get cryptocurrency market data using quantmod by writing a wrapper function foo around the cryptoQuotes::getQuote()-function.

Minimal, reproducible example

Below is an example of how the cryptoQuotes::getQuote()-function works, and what it outputs.

 # Get BTC and display
 # latest prices
 tail(
     BTC <- cryptoQuotes::getQuote(
         ticker = "BTCUSDT",
         interval = "1d"
     )
 )
#>               Open    High     Low   Close   Volume
#> 2024-02-09 45269.2 48230.3 45218.1 47116.1 519919.4
#> 2024-02-10 47116.1 48189.6 46836.4 47732.6 179626.6
#> 2024-02-11 47732.6 48600.0 47539.4 48303.4 209951.6
#> 2024-02-12 48303.4 50413.2 47702.0 49943.6 450895.2
#> 2024-02-13 49943.6 50428.8 48301.0 49696.4 382348.1
#> 2024-02-14 49696.4 49717.3 49215.7 49585.0  37881.4

 # print class
 class(BTC)
#> [1] "xts" "zoo"

Created on 2024-02-14 with reprex v2.1.0

I believe the addition will be a trivial exercise, and can be done without altering any code other than the NAMESPACE.

Possible caveats/isssues

cryptoQuotes uses httr2 and cli for interacting with the public market data endpoints, and error-handling. While quantmod uses curl and base R for the same.

braverock commented 4 months ago

the FinancialInstrument package has a 'depends' on quantmod (to ensure that quantmod is present and in the search path), and implements the 'FI' method for getSymbols.

it seems like the cryptoQuotes package could do something similar for getQuotes which would implement a src='cryptoQuotes' method for quantmod::getQuote. This would make the additional dependencies only relevant if a user already has/wants cryptoQuotes functionality.

serkor1 commented 4 months ago

This solution sounds super interesting, and not something I am familiar with, at all - so please bear with me. If quantmod::getQuote should have the opportunity to use src="cryptoQuotes", wouldn't quantmod be required to take dependency on cryptoQuotes and not the other way around, if anything?

Is this FI-method you are referring to?

braverock commented 4 months ago

see, e.g. quantmod:::getQuote.tiingo or quantmod:::getQuote.yahoo for getQuote specific examples inside quantmod itself.

The implementation is one of an S3 method. So cryptoQuotes would add Depends on quantmod to its DESCRIPTION file, you would implement a getQuote.cryptoQuotes function in cryptoQuotes, and then you would export(getQuote.cryptoQuotes) in your NAMESPACE file.

it should then 'just work' without any changes in quantmod ;)

serkor1 commented 4 months ago

The infamous S3-method! I wasn't aware that this could be done across R-packages! Should I just close the issue if its that simple, then?

braverock commented 4 months ago

might as well keep it open for now in case there are problems, but it should 'just work' (famous last words)

you should be able to report success and close it 'soon'.

braverock commented 4 months ago

This isn't technically S3 method dispatch, but it is a similar idea on the src argument. S3 dispatch works on the class of the object, and yes it does work cross-package, with various packages exporting S3method 's for core functions such as print and summary and fit.

quantmod dispatches in a nearly identical way on the src argument for getQuote and getSymbols, looking for a getQuote.[src] function as defined by the argument to src.

joshuaulrich commented 4 months ago

Thanks for reaching out @serkor1! I agree with @braverock; this is something you can do without changing quantmod. Also, I would not want to maintain this in quantmod because I live in the US and can't directly access many of the crypto exchange APIs.

So I'm going to close this as 'not planned', but please feel free to continue the discussion and ask questions here. I'll do my best to help.


For what it's worth, I personally do not use 'httr2', 'cli', or most packages from Hadley's team because I don't trust them to maintain long-term stable interfaces. Their opinions seem to change a lot and I don't have patience for unnecessary breaking changes, "soft-deprecation" warnings, or other noise due to changes that aren't strictly necessary. My experience is also that their package source code is usually over-complicated and difficult to follow... which matters to me because the help pages are often terse and not very useful, so I resort to looking at the source code to try and understand how the functions work.


I released quantmod to CRAN yesterday and they alerted me to failing test in 'cryptoQuotes'. They thought it was due to the quantmod update, but it doesn't look like 'cryptoQuotes' actually uses quantmod even though it's listed in 'Suggests'. The failing test was for getLSRatio(). I see many of the package tests are checking the response of an API endpoint request. Those are not good tests to run on CRAN. They will fail if anything unexpected happens with the endpoint, even when it's something you can't fix. You can use an environment variable to only run those tests on your machine and/or during CI/CD. Here's an example of how I test getQuote().

'cryptoQuotes' exports several functions with the same name as quantmod functions. That's likely to cause issues for users because whether quantmod::addMACD() or cryptoQuotes::addMACD() is called will depend on whether they attached quantmod and cryptoQuotes first.