Tuesday, August 28, 2012

XChange - Open Source Java API for MtGox Bitcoin Exchange


UPDATE March 9, 2013: Version 1.5.0 released. Support for 10 exchanges.

UPDATE Jan 31, 2013: Version 1.4.0 released. Support for Canadian Virtual Exchange. Mostly bug fixes.

UPDATE Jan 16, 2013: Version 1.3.0 released. Support for many more exchanges. See release notes and also XChange Release 1.3.0 Announcement

UPDATE Oct 11, 2012: Version 1.2.0 released. Support for Canadian Virtual Exchange.

Supported Exchanges

Together with other members from the Bitcoin community, I've recently created a new open source Java library called XChange. XChange is a Java library providing a simple and consistent API for interacting with a diverse set of financial security exchanges including Bitcoin. The first exchange implemented is the world's largest Bitcoin exchange - Mt Gox. The plan is to add more Bitcoin exchanges and other traditional financial exchanges offerring trading APIs such as Interactive Brokers.

As of the most recent release 1.1.0, Xchange offers the following functionality:
  • Support for MtGox Bitcoin Exchange (public) polling market data (ticker, depth, trades, etc.)
  • Support for MtGox Bitcoin Exchange (private) polling trade data (account info, market order, limit order, cancel order open orders, etc.)
  • Support for MtGox Bitcoin Exchange (public) streaming market (ticker)
Next up on the todo list is:
  • Support for MtGox Bitcoin Exchange (public) streaming market (depth, trades, etc.)
  • Support for MtGox Bitcoin Exchange (private) streaming trade data (account info, market order, limit order, cancel order open orders, etc.)

Relevant Links

Project Home - http://xeiam.com/xchange.jsp
Code on Github - https://github.com/timmolter/XChange
Example Code - http://xeiam.com/xchange_examplecode.jsp

Examples

The following examples demonstrate getting Ticker data from MtGox, first using the polling API, and second using the streaming API.

Ticker via Polling API

package com.xeiam.xchange.examples.mtgox.v1.polling;

import com.xeiam.xchange.Currencies;
import com.xeiam.xchange.Exchange;
import com.xeiam.xchange.ExchangeFactory;
import com.xeiam.xchange.dto.marketdata.Ticker;
import com.xeiam.xchange.service.marketdata.polling.PollingMarketDataService;

/**
 * Test requesting polling Ticker at MtGox
 */
public class TickerDemo {

  private static PollingMarketDataService marketDataService;

  public static void main(String[] args) {

    // Use the factory to get the version 1 MtGox exchange API using default settings
    Exchange mtGox = ExchangeFactory.INSTANCE.createExchange("com.xeiam.xchange.mtgox.v1.MtGoxExchange");

    // Interested in the public polling market data feed (no authentication)
    marketDataService = mtGox.getPollingMarketDataService();

    // Get the latest ticker data showing BTC to USD
    Ticker ticker = marketDataService.getTicker(Currencies.BTC, Currencies.USD);
    double value = ticker.getLast().getAmount().doubleValue();
    String currency = ticker.getLast().getCurrencyUnit().toString();
    System.out.println("Last: " + currency + "-" + value);

    System.out.println("Last: " + ticker.getLast().toString());
    System.out.println("Bid: " + ticker.getBid().toString());
    System.out.println("Ask: " + ticker.getAsk().toString());

    // Get the latest ticker data showing BTC to EUR
    ticker = marketDataService.getTicker(Currencies.BTC, Currencies.EUR);
    System.out.println("Last: " + ticker.getLast().toString());
    System.out.println("Bid: " + ticker.getBid().toString());
    System.out.println("Ask: " + ticker.getAsk().toString());

    // Get the latest ticker data showing BTC to GBP
    ticker = marketDataService.getTicker(Currencies.BTC, Currencies.GBP);
    System.out.println("Last: " + ticker.getLast().toString());
    System.out.println("Bid: " + ticker.getBid().toString());
    System.out.println("Ask: " + ticker.getAsk().toString());

  }

}
Result:
Last: USD-5.14739
Last: USD 5.14739
Bid: USD 5.12011
Ask: USD 5.1299

Last: EUR 4.07
Bid: EUR 4.0527
Ask: EUR 4.07

Last: GBP 3.3452
Bid: GBP 3.3
Ask: GBP 3.34091

Ticker via Streaming API

package com.xeiam.xchange.examples.mtgox.v1.streaming;

import java.util.concurrent.BlockingQueue;

import com.xeiam.xchange.Currencies;
import com.xeiam.xchange.Exchange;
import com.xeiam.xchange.dto.marketdata.Ticker;
import com.xeiam.xchange.mtgox.v1.MtGoxExchange;
import com.xeiam.xchange.service.marketdata.streaming.StreamingMarketDataService;

/**
 * Test requesting streaming Ticker at MtGox
 */
public class TickerDemo {

  public static void main(String[] args) {

    TickerDemo tickerDemo = new TickerDemo();
    tickerDemo.start();
  }

  private void start() {

    // Use the default MtGox settings
    Exchange mtGox = MtGoxExchange.newInstance();

    // Interested in the public streaming market data feed (no authentication)
    StreamingMarketDataService streamingMarketDataService = mtGox.getStreamingMarketDataService();

    // Get blocking queue that receives streaming ticker data
    BlockingQueue tickerQueue = streamingMarketDataService.requestTicker(Currencies.BTC, Currencies.USD);

    // take streaming ticker data from the queue and do something with it
    while (true) {
      try {
        // Put your ticker event handling code here
        doSomething(tickerQueue.take());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * Do something fun with the streaming data!
   * 
   * @param ticker
   */
  private void doSomething(Ticker ticker) {

    System.out.println(ticker.toString());
  }

}
Result:
Ticker [timestamp=2012-08-26T20:09:13.202Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3078691906206]
Ticker [timestamp=2012-08-26T20:09:18.651Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:19.568Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:23.152Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:23.975Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:24.790Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:25.205Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:26.018Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Ticker [timestamp=2012-08-26T20:09:26.543Z, last=USD 10.6, bid=USD 10.55248, ask=USD 10.6, tradableIdentifier=BTC, volume=3068691906206]
Piece of Cake!!!

Monday, August 27, 2012

Running Average and Running Standard Deviation in Java

Today I needed to generate statistics for a simulation in real-time, which forced me to code a class that calculates the running average and running standard deviation of incoming data. I remember doing this a long time ago for another project based on MATLAB, but today I needed a Java implementation. The following code example shows how to calculate the running average and running standard deviation for streaming data. Thanks to Subluminal Messages for the simple math implementation!

The Code

public class RunningStatDemo {

  public static void main(String[] args) {

    RunningStatDemo rsd = new RunningStatDemo();
    rsd.go();
  }

  private void go() {

    RunningStat rs = new RunningStat();
    rs.put(1);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(1);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(10);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(20);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(50);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(50);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());
  }

  public class RunningStat {

    private int count = 0;
    private double average = 0.0;
    private double pwrSumAvg = 0.0;
    private double stdDev = 0.0;

    /**
     * Incoming new values used to calculate the running statistics
     * 
     * @param value
     */
    public void put(double value) {

      count++;
      average += (value - average) / count;
      pwrSumAvg += (value * value - pwrSumAvg) / count;
      stdDev = Math.sqrt((pwrSumAvg * count - count * average * average) / (count - 1));

    }

    public double getAverage() {

      return average;
    }

    public double getStandardDeviation() {

      return Double.isNaN(stdDev) ? 0.0 : stdDev;
    }

  }

}

Results

ave: 1.0
std: 0.0
ave: 1.0
std: 0.0
ave: 4.0
std: 5.196152422706632
ave: 8.0
std: 9.055385138137417
ave: 16.4
std: 20.354360712142253
ave: 22.0
std: 22.794736234490628

Piece of Cake!!!

Sunday, August 26, 2012

Create Javadocs for a Multi-Module Maven Project

In this tutorial, I show how to create Javadocs for a multi-module Maven project. Creation of Javadocs requires the use of the Maven maven-javadoc-plugin plugin and running "mvn javadoc:aggregate" on the parent pom.xml. For the sake of this tutorial, I'm taking some excerpts from one of my current Open Source Projects - XChange.

Relevant Links

XChange on Github - To see an actual working example
Javadocs for XChange on xeiam.com - To see what the generated Javadocs look like.

How To

Step 1: Add the following to the parent pom.xml file:

<build>
  <pluginmanagement>
    <plugin>
      <groupid>org.apache.maven.plugins</groupId>
      <artifactid>maven-javadoc-plugin</artifactId>
      <version>2.8.1</version>
    </plugin>
  </pluginManagement>
  <plugins>
    <plugin>
      <groupid>org.apache.maven.plugins</groupId>
      <artifactid>maven-javadoc-plugin</artifactId>
    </plugin>
  </plugins>
</build>
Step 2: Run the following mvn command:

mvn javadoc:aggregate

Piece of Cake!!!

See also: Maven Project Compiles in Eclipse but Maven Build Fails
See also: Using Maven Offline
See also: Hello World - Maven, M2Eclipse and Eclipse

Saturday, August 25, 2012

Java XChart Library Now Supports Error Bars

XChart provides a super light-weight and dependency-free charting API for Java. It is open source, hosted on Github, and is licensed with an Apache 2.0 license. I created it over a year ago because I was looking for and couldn't find an easy-to-use plotting library for Java that was similar to the MATLAB's charting tool. I tried JFreeChart of course, but I found that the learning curve was very steep. Like MATLAB's charting functions, I just wanted to simply pass my data to an API, and after a few lines of code, have a plot.

I just recently added support in XChart for making plots with error bars, which is what this post is about. The following demo, shows how to add error bars to an XChart chart. BTW, if you have any feature requests for XChart, please feel free to open a new issue on Github here. For more XChart exmaples go here.

XChart - Open Source Charting API

To use XChart, you first need to get the XChart jar, which is available here. If you use Maven, just add the following to your dependencies in pom.xml:
<dependency>
  <groupId>com.xeiam</groupId>
  <artifactId>xchart</artifactId>
  <version>1.1.0</version>
</dependency>

The XChart artifacts are currently hosted on the Xeiam Nexus repository here:
<repositories>
  <repository>
    <id>xchange-release</id>
    <releases/>
    <url>http://nexus.xeiam.com/content/repositories/releases</url>
  </repository>
  <repository>
    <id>xchange-snapshot</id>
    <snapshots/>
    <url>http://nexus.xeiam.com/content/repositories/snapshots/</url>
  </repository>
</repositories>

Error Bars Example Code

package com.xeiam.xchart.example;

import java.util.ArrayList;
import java.util.Collection;

import com.xeiam.xchart.Chart;
import com.xeiam.xchart.series.Series;
import com.xeiam.xchart.series.SeriesColor;
import com.xeiam.xchart.series.SeriesLineStyle;
import com.xeiam.xchart.series.SeriesMarker;
import com.xeiam.xchart.swing.SwingWrapper;

/**
 * Create a Chart with error bars
 * 
 * @author timmolter
 */
public class Example8 {

  public static void main(String[] args) {

    // generates data
    int size = 10;
    Collection xData1 = new ArrayList();
    Collection yData1 = new ArrayList();
    Collection errorBars = new ArrayList();
    for (int i = 0; i <= size; i++) {
      xData1.add(i);
      yData1.add(10 * Math.exp(-i));
      errorBars.add(Math.random() + .3);
    }

    // Create Chart
    Chart chart = new Chart(600, 400);

    // Customize Chart
    chart.setChartTitleVisible(false);
    chart.setChartLegendVisible(false);
    chart.setAxisTitlesVisible(false);

    // Series 1
    Series series1 = chart.addSeries("10^(-x)", xData1, yData1, errorBars);
    series1.setLineColor(SeriesColor.PURPLE);
    series1.setLineStyle(SeriesLineStyle.DASH_DASH);
    series1.setMarkerColor(SeriesColor.GREEN);
    series1.setMarker(SeriesMarker.SQUARE);

    new SwingWrapper(chart).displayChart();
  }

}

Resulting Plot

Piece of Cake!!! See also: Java Web Apps - Integrating Charts into a Servlet