JAVA: VaR – BitCoin/USD

VaR – value at risk – is a risk measurement used in financial markets, risk management and financial reporting. So, simply said, VaR shows how much you are most likely to lose in the worst days of trading. The advantage of VaR is that is simple and intuitive (and is used for a bunch of stuff, mostly to calculate losses that can be incurred by having some assets and liabilities in foreign currencies). To calculate VaR you must specify a probability of that loss, usually between 1% and 5%. VaR for a specific number of days ahead is calculated using this formula:

VaRvolatility * quantile * portfolio size * sqrt(days ahead/days in year)

For most calculations for days in year, people use 252 – working days, as currency exchange rates remain unchanged during weekend days, but for BitCoin/USD exchange rate we’re going to use 365, because there is no diminished activity on the BitCoin/USD market during weekends. The confidence level we’re going to use is 95% ( so the quantile corresponding to a 95% probability is 1.65, you can find this out using statistics table or the NORMSINV function in Microsoft Excel) and we’re going to say that our portfolio consists out of 200 BitCoins. Also, we’re going to suppose that we want to know the VaR for the next 10 days:

VaRvolatility * 1.65 *  200BTC value in USD * sqrt(10/365)

Next step, is calculating the volatility:

σ = standard deviation of return * sqrt(365)

standard deviation:

σ of return = sqrt[1/N * power(sumof(x – average), 2)]

As we can see, VaR has no specific theory behind or calculations, it just uses the volatility for a specific period to anticipate future movements of the BTC/USD rate. First thing we’re going to do is to get the daily BTC/USD rate for the past year and calculate the standard deviation, then the volatility. We’re multiplying the standard deviation to the square root of 365 because variance increases linearly with time, so the standard deviation is the square root of variance and time.

Here’s how it looks in Java (we’re using data provided by CoinDesk.com):

package com.wordpress.breekmd;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import java.util.Map;

import com.json.parsers.JSONParser;
import com.json.parsers.JsonParserFactory;

public class Main {

	public static void main(String[] args) {
		StringBuffer text = new StringBuffer();

		// declaring and initiliasing variables
		double sumOfReturn = 0d;
		double averageOfReturn;
		double std_dev;
		double annualVolatility;
		double VaR;
		double portfolioValue = 0;

		ArrayList<Double> list = new ArrayList<Double>();  // the list of daily BTC prices
		ArrayList<Double> returnList = new ArrayList<Double>(); // the list of daily BTC price evolution, named as return
		// Return = Price of day n divided by price of day n-1, in %

		Calendar end = Calendar.getInstance();
		end.add(Calendar.DAY_OF_MONTH, -2); // we substract 2 days because the data may not be updated to latest day

		Calendar date = Calendar.getInstance();
		date.add(Calendar.YEAR, -1); // we substract depending on the period we want to calculate the volatility for
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

		try {
			// creating the URL using StringBuffer
			StringBuffer urlBuffer = new StringBuffer();
			urlBuffer.append("https://api.coindesk.com/v1/bpi/historical/close.json?start=");
			urlBuffer.append(df.format(date.getTime()));
			urlBuffer.append("&end=");
			urlBuffer.append(df.format(end.getTime()));
			URL url = new URL(urlBuffer.toString());
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line;
			while ((line = reader.readLine()) != null ) {
				text.append(line);
			}
			reader.close();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (ProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		//parsing the JSON data
		JsonParserFactory factory = JsonParserFactory.getInstance();
		JSONParser parser = factory.newJsonParser();
		Map data = parser.parseJson(text.toString());
		Map prices = (Map) data.get("bpi");

		// calculating portfolio data using latest prices
		portfolioValue = 200 * Double.parseDouble((String) prices.get(df.format(end.getTime())));

		while (date.before(end)) {  // looking up each date in the parsed data and getting the price
			list.add(Double.parseDouble((String) prices.get(df.format(date.getTime()))));
			date.add(Calendar.DAY_OF_MONTH, 1);
		}

		for (int i = 1; i <= list.size() - 1; i++) { // calculating daily return and adding it to the return list
			returnList.add(list.get(i)/list.get(i-1)*100 - 100);
		}

		for (Double returnValue : returnList) { // getting the sum of returns
			sumOfReturn += returnValue;
		}

		averageOfReturn = sumOfReturn/returnList.size(); // calculating average of returns
		std_dev = getStdDev(returnList, averageOfReturn); // standard deviation using the method
		annualVolatility = std_dev * Math.sqrt(365d); // transforming standard deviation in annual volatility
		VaR = annualVolatility/100 * Math.sqrt(10/365d) * portfolioValue * 1.65;  

		Locale usd = new Locale("en","US");
		NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(usd);
		System.out.println("Value at risk for 200 BTC during next 10 days equals " + currencyFormat.format(VaR)); //
	}

	private static double getStdDev(ArrayList<Double> list, double average) {
		Double sumOfDiff = 0d;
		for (Double returnValue : list) {
			sumOfDiff += Math.pow(returnValue - average, 2)/list.size();  // formula of standard deviation
		}
		return Math.sqrt(sumOfDiff);
	}
}

Indeed, VaR based on historical data is the simplest way to do it, but also the least precise and most primitive way to do it. There are a lot of different ways to calculate VaR, like using Monte Carlo or some additional conditions.

Leave a comment