I wrote this simple R script to keep track of crypto portfolio and evaluate realtime portfolio worth in any fiat or crypto

in #programming8 years ago (edited)

Script is here.
This is a simple R script to keep track of crypto investment. The script enables user to record and track investments with two functions:

<pre><code>add_trade() <p dir="auto">with which user can record transactions, <em>e.g., deposit, withdraw or exchange. And <pre><code>portfolio_value() <p dir="auto">which evaluates real time portfolio value in user specified crypto or fiat currency. We'll create a function to make naive price prediction as well as the two functions mentioned. <p dir="auto">First, check if required packages are installed. If not, install them: <pre><code>if (!require("jsonlite")) install.packages("jsonlite") if (!require("dplyr")) install.packages("dplyr") if (!require("ggplot2")) install.packages("ggplot2") if (!require("forecast")) install.packages("forecast") if (!require("plotrix")) install.packages("plotrix") <p dir="auto">It's a good practice save trade history in disk. We'll save it as .csv file which allows analysis using other software as well. The below code chunk checks if there's a file named <code>trade_histoy.csv in user's working directory. If not, the code will create one. Issue <code>getwd() to see current working directory and <code>setwd(<directory path>) to set working directory. <pre><code>if(!file.exists("trade_history.csv")){ trade_history <- data.frame(type=factor(levels = c("deposit", "wtihdraw", "exchange")), deposit_amount=double(), deposit_currency=factor(), withdraw_amount=double(), withdraw_currency=factor(), exchange_name=character(), remark=character(), date=character(), # year-month-day format eg 2017-07-18 stringsAsFactors=FALSE) write.csv(x = trade_history, file = "trade_history.csv", sep = ",", row.names = FALSE) } <p dir="auto">We inspect what our old or newly created <em>trade_history.csv contains. First load the data with <code>read.csv() function, store that data in an R variable named <code>trade_history and see top few rows of that R variable with <code>head(trade_history: <pre><code>trade_history <- read.csv(file = "trade_history.csv", header = TRUE, sep = ",") head(trade_history) <p dir="auto">Output of <code>head(trade_history) is: <pre><code>[1] type deposit_amount deposit_currency withdraw_amount withdraw_currency exchange_name remark date <0 rows> (or 0-length row.names) <p dir="auto">Since we haven't yet entered any trade/transaction, it's a dataset with 0 rows. Lets create the function named <code>add_trade() so we can add transactions easier: <pre><code>add_trade <- function(type, deposit_amount = 0, deposit_currency = NA, withdraw_amount = 0, withdraw_currency = NA, exchange_name = NA, remark = NA, date = NA) { new_trade <- data.frame(type, deposit_amount, deposit_currency, withdraw_amount, withdraw_currency, exchange_name, remark, date) read.csv(file = "trade_history.csv", header = TRUE, sep = ",") %>% rbind(new_trade) -> "trade_history" write.csv(x = trade_history, file = "trade_history.csv", sep = ",", row.names = FALSE) assign(x = "trade_history", trade_history, envir = globalenv()) } <p dir="auto">Now add a few transactions with the function <code>add_trade() we just created: <pre><code>add_trade(type = "deposit", deposit_amount = 0.2, deposit_currency = "BTC", remark = "gift from brother", date = "2017-07-01") add_trade(type = "deposit", deposit_amount = 5, deposit_currency = "XMR", remark = "purchased", exchange_name = "poloniex", date = "2017-07-02") add_trade(type = "deposit", deposit_amount = 1, deposit_currency = "ETH", remark = "mining reward", date = "2017-07-05") add_trade(type = "deposit", deposit_amount = 200, deposit_currency = "STEEM", remark = "Steemit rewarrd", date = "2017-07-06") add_trade(type = "trade", deposit_amount = 1.1, deposit_currency = "ZEC", withdraw_amount = 0.1, withdraw_currency = "BTC", remark = "Exchanged BTC for ZEC", date = "2017-07-09") add_trade(type = "trade", deposit_amount = 4.6, deposit_currency = "ETC", withdraw_amount = 2, withdraw_currency = "XMR", remark = "Exchanged XMR ETC", date = "2017-07-10") add_trade(type = "trade", deposit_amount = 65, deposit_currency = "EOS", withdraw_amount = 0.5, withdraw_currency = "ETH", date = "2017-07-14") add_trade(type = "withdraw", withdraw_amount = 0.5, withdraw_currency = "XMR", remark = "lost wallet key") <p dir="auto">See our first 5 transactions (rows) of trade history by running <code>head(trade_history, 8) <pre><code> type deposit_amount deposit_currency withdraw_amount withdraw_currency exchange_name remark date 1 deposit 0.2 BTC 0.0 <NA> <NA> gift from brother 2017-07-01 2 deposit 5.0 XMR 0.0 <NA> poloniex purchased 2017-07-02 3 deposit 1.0 ETH 0.0 <NA> <NA> mining reward 2017-07-05 4 deposit 200.0 STEEM 0.0 <NA> <NA> Steemit rewarrd 2017-07-06 5 trade 1.1 ZEC 0.1 BTC <NA> Exchanged BTC for ZEC 2017-07-09 <p dir="auto">Note that we don't need to supply values for all the arguments. Empty argument values default to <code>NA. This, however, doesn't provide compact info about our portfolio. Let's create a function and name it <code>portfolio() that will: <pre><code>portfolio <- function() { deposit <- aggregate(trade_history[c("deposit_amount")], by = trade_history[c("deposit_currency")], FUN=sum) names(deposit) <- c("currency", "deposit_amount") withdraw <- aggregate(trade_history[c("withdraw_amount")], by = trade_history[c("withdraw_currency")], FUN=sum) names(withdraw) <- c("currency", "withdraw_amount") portfolio <- full_join(x = deposit, y = withdraw, by = "currency") portfolio[is.na(portfolio)] <- 0 portfolio$available <- portfolio$deposit_amount - portfolio$withdraw_amount assign(x = "portfolio", portfolio, envir = globalenv()) print(portfolio) } <p dir="auto">Unlike <code>add_trade(), this <code>portfolio() function doesn't take any argument. Just issue <code>portfolio() which in our case returns a compact table: <pre><code> currency deposit_amount withdraw_amount available 1 BTC 0.2 0.1 0.1 2 EOS 65.0 0.0 65.0 3 ETC 4.6 0.0 4.6 4 ETH 1.0 0.5 0.5 5 STEEM 200.0 0.0 200.0 6 XMR 5.0 2.5 2.5 7 ZEC 1.1 0.0 1.1 <p dir="auto">If were to know how much the portfolio is worth in, say, USD, EUR, CNY or BTC? Let's create a function <code>portfolio_value() that will do our job: <pre><code>portfolio_value <- function(priced_in) { for(i in 1:nrow(portfolio)) { url <- paste0("https://min-api.cryptocompare.com/data/price?fsym=", portfolio[i, 1], "&tsyms=", priced_in, collapse = "") unit_price <- fromJSON(url)[[1]] portfolio$value[i] <- unit_price * portfolio$available[i] } assign(x = "portfolio_value", portfolio, envir = globalenv()) print(portfolio_value) print(paste("Total portfolio value in", priced_in, sum(portfolio_value$value))) lbls <- paste0(portfolio$currency, " : ", # Create labels for plot sprintf("%.2f", (portfolio$value / sum (portfolio$value))*100), "%") pie3D(portfolio$value, labels = lbls, explode=0.1, main="Portfolio value") } <p dir="auto">The <code>portfolio_value() function takes one argument - the currency in which we want to evaluate our portfolio. Standard symbols are accepted like, USD, EUR, BTC, ETH. I would like to know how much it's worth in Chinese Yuan symbled CNY:<br /> So I execute <code>portfolio_value("CNY") which returns the below table as well as the pie chart: <pre><code> currency deposit_amount withdraw_amount available value 1 BTC 0.2 0.1 0.1 1585.070 2 EOS 65.0 0.0 65.0 729.950 3 ETC 4.6 0.0 4.6 491.418 4 ETH 1.0 0.5 0.5 767.625 5 STEEM 200.0 0.0 200.0 1724.000 6 XMR 5.0 2.5 2.5 620.150 7 ZEC 1.1 0.0 1.1 1466.366 [1] "Total portfolio value in CNY 7384.579" <p dir="auto"><br /><br /> <center><img src="https://images.hive.blog/768x0/https://steemitimages.com/DQmQGbzoVGHYsiJ1owBd2UYPzViSLKkZwVhtqEzFqNiFPey/Rplot-portfolio.jpeg" alt="Rplot-portfolio.jpeg" srcset="https://images.hive.blog/768x0/https://steemitimages.com/DQmQGbzoVGHYsiJ1owBd2UYPzViSLKkZwVhtqEzFqNiFPey/Rplot-portfolio.jpeg 1x, https://images.hive.blog/1536x0/https://steemitimages.com/DQmQGbzoVGHYsiJ1owBd2UYPzViSLKkZwVhtqEzFqNiFPey/Rplot-portfolio.jpeg 2x" /> <p dir="auto">We might be interested in some predictive analysis of portfolio performance. Let's see how we can make prediction using simple method. I would like to know how BTC is going to perform in the next 30 days against USD. Let's create a function so we can do same thing for all currencies: <pre><code>predict_currency <- function(currency, priced_in, period) { url <- paste0("https://min-api.cryptocompare.com/data/histoday?fsym=", currency, "&tsym=", priced_in, "&allData=true", collapse = "") histoday <- fromJSON(url) ts <- ts(histoday$Data$close, start = histoday$Data$time[1]) fit_arima <- auto.arima(ts) autoplot(forecast(fit_arima, period)) } <p dir="auto">Now run <code>predict_currency("BTC", "USD", 30). It generates the below graph in which colored region indicates the likely price of BTC in USD in the next 30 days: <p dir="auto"><img src="https://images.hive.blog/768x0/https://steemitimages.com/DQmQDjya695mXgBULD3WMrwmBMbdJzfkSdVUB6Wiamj6M8c/Rplot-prediction.jpeg" alt="Rplot-prediction.jpeg" srcset="https://images.hive.blog/768x0/https://steemitimages.com/DQmQDjya695mXgBULD3WMrwmBMbdJzfkSdVUB6Wiamj6M8c/Rplot-prediction.jpeg 1x, https://images.hive.blog/1536x0/https://steemitimages.com/DQmQDjya695mXgBULD3WMrwmBMbdJzfkSdVUB6Wiamj6M8c/Rplot-prediction.jpeg 2x" /> <p dir="auto">Run for, example, <code>predict currency("ETH", "BTC", 7) to get estimated ETH price in BTC for the next 7 days. It would be nice to create a predictive function for our portfolio like: <pre><code>predict_portfolio <- fuction (period) { # do things } <p dir="auto">We'll do this in the next post. <p dir="auto">I just uploaded the script in my <a href="https://github.com/cryptovest/portfolio" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">git repo. Feel free to contribute and provide suggestion to improve code so it can be actually be used by others. Thanks!
Sort:  

really nice work

Thanks! I'm going to work on creating a user friendly web interface so user can interact with data using mouse and browser only. There needs to be a lot more functionalities as well in order for the project to be practically useful. Hoping that's going to be something useful. Also, since R has powerful statistical analysis tools/packages, having structured data in R environment is a plus.

I've done hundreds of buys and sells across a number of tokens going back to late 2013 and have tracked everything to the penny with excel. It's such a pain!

Try edit(trade_history) for an Excel like spreadsheet which lets you enter values in cells. You can import Excel files as well.

This is definitely the quality of sharing I hoped to find on #steemit!

Much appreciated!

haha that meme

excelente aporte amigo, sigue adelante felicidades, sera un gran proyecto

click here!This post received a 4.4% upvote from @randowhale thanks to @cryptovest! For more information,

Hey gutted I have only seen this now tried to learn R a while back but needed some extra guidance . If you could get in contact that would be great would like to learn more about R .