So I'm continuing to exercise the HTTP Request (new in JMP 14) object in JSL. (Although my JSL is a little rough, I am getting better at it.)
I came across Bitcoincharts, (https://bitcoincharts.com) and thought I’d see if I could make heads or tails of this thing called “bitcoin”.
The Rest API can be found here: https://bitcoincharts.com/about/exchanges/
and here: https://bitcoincharts.com/about/markets-api/
I’m going to make use of the endpoints
http://api.bitcoincharts.com/v1/weighted_prices.json
http://api.bitcoincharts.com/v1/markets.json
and
http://api.bitcoincharts.com/v1/trades.csv
described in the api.
I’m also going to be making use of JSL namespaces as a way to organize the script and make things easier.
To get the list of weighted prices in JSL, I do this:
bitcoincharts:request << Reset (
URL(bitcoincharts:url || "/weighted_prices.json"),
Method("Get")
);
json = bitcoincharts:request << Send();
If(!IsEmpty(json),
bitcoincharts:weighted = ParseJSON(json);
bitcoincharts:prices_now = bitcoincharts:GMT Time (bitcoincharts:weighted["timestamp"]);
);
Where I just reuse the http request (bitcoincharts:request) by sending the Reset message to it with the appropriate URL and Method and then send the Send message and capturing the return value. Since I expect the return to be JSON data, I just check for Empty(…) before parsing it into an Associative Array with JSON Parse. This Associative Array now contains the key/value pairs where the Key is the currency and the Value an Associative Array that contains the “24h”, “30d”, “7d” price for that currency. You can click on a currency in the currency column to see the datatable. (One interesting note is that this datatable is created by turning an Associative Array, the prices for the currency, into a JSON Expression and using JSON to Data Table)
To get market data (the main data table), I do this:
bitcoincharts:request << Reset (
URL(bitcoincharts:url || "/markets.json"),
Method("Get")
);
json = bitcoincharts:request << Send();
Where I just reuse the http request (bitcoincharts:request again) by sending the Reset message to it with the appropriate URL and Method and then send the Send message and capturing the return value. Since I expect the return to be JSON data, I just check for Empty(…) before I us JSON to Datatable to turn it into a JMP Datatable. (One interesting note is that I use:
dt = Open("https://en.wikipedia.org/wiki/ISO_4217",
HTML Table( 2, Column Names( 1 ), Data Starts( 2 ) ), Invisible);
bitcoincharts:currencies = Associative Array(As List(dt:Code << Get Values), As List(dt:Currency << Get Values));
To retrieve a currency code and detail information into an Associative Array. That is I want say, a USD => US Dollar mapping. I’ve found this way of creating an Associative Array very useful)
To get historical data, I do this:
query = [=>];
query["symbol"] = symbol;
bitcoincharts:request << Reset (
URL(bitcoincharts:url || "/trades.csv"),
Method("Get"),
Query String(query)
);
csv = bitcoincharts:request << Send;
columns = Concat Items({"unixtime", "price", "amount"}, ",") || "\!n";
If(!IsEmpty(csv),
csv = columns || csv;
,
csv = columns;
);
f = Save Text File("$Temp/" || symbol || ".csv", csv, "replace");
dt = Open(f, "invisible");
This uses an Associative Array to create a Query String for the HTTP Request. If the symbol is btcoidIDR, then it effectively builds the URL like:
http://api.bitcoincharts.com/v1/trades.csv?symbol=btcoidIDR
The return is CSV data with no column headers, so I needed to create the column headers, append the data to it, then save it to a text file and call open to get the datatable. I could have just created datatable all in JSL, but I opted to let JMP do it all for me.
I added a couple other Table scripts that allow the “stacking” of weighted prices and trade data when you multi-select the rows and click the script as well as archiving things.
Over all it was a fun script to write and explore.
Enjoy!