Dark Planet Development Platform

Get Dark Planet Development Platform at SourceForge.net. Fast, secure and Free Open Source software downloads

EVE Market Data API

The EVE Market Data API provides methods for loading and accessing EVE market data either exported from the EVE client or loaded from one of the various third party sources such as eve-marketdata or eve-central. The market data API makes use of the persistence API as market data records are convenient to access using a database. As such, the main gateway interface, org.dps.core.market.IEveMarketData, provides the session and query access methods begin, getSession, commit, rollback and close. See the Persistence API section for a detailed description of these methods. We provide a few simple examples showing how to use these methods below.

API Overview

The market API provides access to two types of data: Market orders are represented by instances of IExternalMarketOrderRecord. The fields of the external market order interface mostly correspond to the fields you would see in the comma separate value (CSV) file that is created when you export market data in the EVE client. These fields are:

Field Description Notes
long orderID Unique ID of the order entry. Not guaranteed to be unique but they ARE longs and so should not recycle frequently. This is a key field.
int typeID The type to buy or sell in the order. This is a key field.
long stationID The station where the order was placed. This is a key field
boolean bid True if the order represents a bid. False otherwise.
int duration Duration in days for which the order is valid. Orders expire at time issued + duration.
long issued Timestamp when order was issued.
int minVolume For bids, the minimum quantity that this order will execute on.
double price Order limit price (per unit).
int range The range over which the order will execute. Sell orders are always executable for the entire region and will have a range value of 32767. See the following table:
RangeMeaning
-1Station
0Solar System
1-45, 10, 20, or 40 jumps respectively
32767Region
int volEntered Initial quantity to be bought or sold. This is constant for the life of the order.
int volRemaining Amount of volume remaining to be executed for the order.
long regionID Region where the order was placed.
long solarSystemID Solar syste where the order was placed.
String source Source from which the data originated. This is a free-form field which can have any value you like. For example, you could use this field to distinguish market data loaded from EVE client export versus market data provided by a third party. This is a key field.
long sampleTime Epoch time representing the time at which the market data was inserted. You are free to use whatever value you like here but the intent is that this field indicates the "freshness" of the data. For example, you could populate this field with the timestamp on an EVE client export file. This field can be used in the market data access interface to filter data based on the time it was loaded.

Most of the market data fields are provided by the various sources from which market data is obtainable. The source field is provided to make it easier to handle data which may be missing some fields. For example, if some source doesn't or can't provide volEntered, then you can use the source field to identify such data and change your code to handle the missing field properly.

For database storage, the tuple (orderID, typeID, stationID, source) should be used as the key. Technically, order IDs can wrap but this seems unlikley given that they are now 64-bit values.

Historic market activity is represented by instances of IExternalHistoricTradeRecord. The fields of the historic trade interface were designed after the historic dumps recently provided by CCP. The provided fields are a superset of the historic price information available in the EVE client. These fields are:

Field Description Notes
int typeID The type of object transacted on the given dat.e This is a key field.
long regionID The region where transactions occurred. This is a key field.
long date The date timestamp for which data is provided. This is a key field and normally represents 00:00:00 UTC for the given date.
long transactionCount The total number of transactions which occurred.
long totalQuantity The total number of units of the given type bought/sold on the given date.
double totalValue The total value (i.e. price * number of units) of all transactions. It is assumed this value is before any tax or brokerage fees.
double minPrice The minimum price for any transaction on the given date.
double maxPrice The maximum price for any transaction on the given date.
double avgPrice The average price for all transactions on the given date.
double medianPrice The median price for all transactions on the given date.
String source Source from which the data originated. This is a free-form field which can have any value you like. For example, you could use this field to distinguish data loaded from EVE client export versus data provided by a third party. This is a key field.

As with market data, the source field is provided to make it easier to handle heterogenous data sets. For database storage, the tuple (typeID, regionID, date, source) should be used as the key.

Inserting Market Data

If you're already familiar with the persistence API, then you know that you can always store records directly once you have access to the appropriate Hibernate session. The market data API provides the standard persistence API methods (i.e. begin, getSession, commit, rollback and close) for exactly that reason. A simple example of using these methods to populate a record is as follows:

    IEveMarketData  marketData = ...get marketdata reference...;
    IEvePersistenceFactory persistFactory = ...get persist reference...;
    
    try {

      marketData.begin();
      IExternalMarketOrderRecord newRecord = persistFactory.getNewExternalMarketOrderRecord(orderID, typeID, stationID, source);
      ...populate other fields of newRecord...
      marketData.getSession().merge(newRecord);
      marketData.commit();

    } catch (HibernateException e) {
      marketData.rollback();
    }

This works for either market orders or historic trade records. The market data API provides a convenience method for each record type to make this slightly easier:

    IEveMarketData  marketData = ...get marketdata reference...;
    IEvePersistenceFactory persistFactory = ...get persist reference...;
    
    try {

      IExternalMarketOrderRecord newRecord = persistFactory.getNewExternalMarketOrderRecord(orderID, typeID, stationID, source);
      ...populate other fields of newRecord...
      marketData.storeEntry(newRecord);

    } catch (HibernateException e) {
      // Commit failed, but storeEntry already rolled back so no need to do that here.
    }

For common tasks, like bulk loading exported market data, the market data API provides the loadExportedClientMarketData method. This method reads market data from an InputStream and will load any data which matches the format of market data exports in the EVE client. As a result, you can use this method to load data from other sources as long as you format it like the EVE client exports. The two other arguments are the sample time and source of the data. Here's an example:

    IEveMarketData  marketData = ...get marketdata reference...;
    
    try {

      // Refer to a file I just exported from the EVE client
      FileInpuStream exportedData = new FileInputStream("Metropolis-Tritanium-2011.06.12 121623.txt");

      // Compute sample time based on the timestamp in the name of the file
      SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      dateParser.setTimeZone(TimeZone.getTimeZone("GMT"));
      long sampleTime = dateParser.parse("2011-06-12 12:16:23").getTime();

      // Now load the data.  I use "EveExport" to indicate client exported data.
      marketData.loadExportedClientMarketData(exportedData, sampleTime, "EveExport");

    } catch (IOException e) {
      // The reference implementation batches record loading so even if an exception
      // is thrown SOME records may have been successfully loaded.
    }    
A similar method, loadExportedHistoricTradeData, can be used to bulk load historic trade information in the format provided by CCP. At time of writing, this format is CSV with fields equivalent to the fields specified on IExternalHistoricTradeRecord with the exception of the source field.

Retrieving Market Data

As with inserting market data, you can retrieve market data directly using the Hibernate-facing methods. Here's a non-trivial example for market orders, the version for historic trades is analagous:

    IEveMarketData  marketData = ...get marketdata reference...;
    
    try {

      // Assemble a fancy query
      int typeid = ...the type we care about...
      long noLaterThan = ...lower bound on sample time so we get fresh data...
      long asOf = ...lowest timestamp after which order was submitted...
      long[] regions = ...array of regions we care about...

      List results;

      // This query selects all the orders for a particular type in a particular set of
      // regions such that the order has not expired and was entered into the db no
      // later than a particular time (i.e. "asOf").  Note that due to type conversion,
      // the query below may not work for some combinations of OS and SQL.  See the
      // reference implementation for a case where this breaks.
      String fancyQuery = "from org.dps.core.persist.IExternalMarketOrderRecord where " +
        "typeID = :typeid and " +
        "issued <= :asof and " +
        "issued + (duration * 86400000) >= :asof" + 
        "sampleTime >= :nolater and" +
        "regionID in " + Arrays.toString(regions).replace('[', '(').replace(']', ')');

      marketData.begin();

      Query select = marketData.getSession().createQuery(fancyQuery);
      select.setInteger("typeid", typeID);
      select.setLong("asof", asOf);
      select.setLong("nolater", noLaterThan);

      // Java will warn about the lack of cast here, a nit with Hibernate but you can ignore
      results = select.list();
      marketdata.commit();

      ...do something interesting with the data...

    } catch (HibernateException e) {
      marketData.rollback();
    }

Since market order selection is a frequent activity, you can use the convenience method getBBO. This method is a bit complicated, here are what the arguments mean:

Argument Meaning
int typeID Restrict selection to items of this type.
long[] regions If non-null and at least one entry, then restrict selection to market data in the listed regions.
long[] solarSystems If non-null and at least one entry, then restrict selection to market data in the listed solar systems. If specified, this overrides restriction by region.
long[] stations If non-null and at least one entry, then restrict selection to market data in the listed stations. If specified, this overrides restriction by region or solar system.
String[] sources If non-null and at least one entry, then restrict selection to market data from the listed sources.
Long ignoreBefore If non-null, then ignore orders with a sample time before the given timestamp.
Long asOf If non-null, then only consider orders active on the given timestamp (i.e. issued >= asOf and not expired).

The result of this method is the best bid/offer or BBO. The BBO is a pair of market orders representing the buy with the highest offer price, and the sell with the lowest ask price. Depending on your query criteria the BBO may have one or more of the following properties:

The EveMarketQuote class provides methods for checking these properties, as well as referencing the sides of the quote.

At time of writing, there are no convenience methods for accessing historic trade data. You'll need to use the Hibernat-facing methods as demonstrated above.