The depth balance code always confused me a bit on first read, so I updated
the comments to make the basic idea more clear in a couple files.  Head
comments for both files, one more comment in the body of MarketDepth.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"JBookTrader" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/jbooktrader?hl=en
-~----------~----~----~----~------~----~------~--~---

package com.jbooktrader.platform.marketdepth;

import com.jbooktrader.platform.marketbook.*;
import com.jbooktrader.platform.model.*;

import java.util.*;

/**
 * The class that tracks bid/ask levels and creates the DepthBalance value.
 *
 *  Depth balance is defined as a relationship between the volume of all
 *    bids and all asks such that:
 *      100  -> Bids account for 100% of the total volume of bids and asks.
 *       0   -> The total volume of bids equals the total volume of asks.
 *     -100  -> Asks account for 100% of the total volume of bids and asks.	
 *
 *    All bid/ask price levels are weighted equally. 
 *   
 *    Balance for the 1 second period is the average of the highest and
 *    lowest balance calculated in the 1 second period.
 */
public class MarketDepth {
    private final LinkedList<MarketDepthItem> bids, asks;
    private boolean isResetting;
    private double lowBalance, highBalance, lastBalance;
    private double midPointPrice;
    private MarketDepthValidator validator;
    private final String name;

    public MarketDepth(String name) {
        this.name = name;
        bids = new LinkedList<MarketDepthItem>();
        asks = new LinkedList<MarketDepthItem>();
        validator = new MarketDepthValidator(bids, asks);
        isResetting = true;
    }

    public void reset() {
        isResetting = true;
        bids.clear();
        asks.clear();
    }


    private int getCumulativeSize(LinkedList<MarketDepthItem> items) {
        int cumulativeSize = 0;
        for (MarketDepthItem item : items) {
            cumulativeSize += item.getSize();
        }
        return cumulativeSize;
    }

    public boolean isValid() {
        return validator.isValid();
    }

    public String getMarketDepthAsString() {
        String md = getCumulativeSize(bids) + "-" + getCumulativeSize(asks);
        long invalidStateDuration = validator.getInvalidStateDurationInSeconds();
        if (invalidStateDuration >= 60) {
            md += ", invalid";
        }

        return md;
    }

    synchronized public void update(int position, MarketDepthOperation operation, MarketDepthSide side, double price, int size) {
        List<MarketDepthItem> items = (side == MarketDepthSide.Bid) ? bids : asks;
        int levels = items.size();

        switch (operation) {
            case Insert:
                if (position <= levels) {
                    items.add(position, new MarketDepthItem(size, price));
                }
                break;
            case Update:
                if (position < levels) {
                    MarketDepthItem item = items.get(position);
                    item.setSize(size);
                    item.setPrice(price);
                }
                break;
            case Delete:
                if (position < levels) {
                    items.remove(position);
                }
                break;
        }


        if (operation == MarketDepthOperation.Update) {
            validator.validate();
            if (validator.isValid()) {
                int cumulativeBid = getCumulativeSize(bids);
                int cumulativeAsk = getCumulativeSize(asks);
                double totalDepth = cumulativeBid + cumulativeAsk;

                // These variables apply only for the latest 1 second period.
                lastBalance = 100d * (cumulativeBid - cumulativeAsk) / totalDepth;
                lowBalance = Math.min(lastBalance, lowBalance);
                highBalance = Math.max(lastBalance, highBalance);
            }

            midPointPrice = (bids.getFirst().getPrice() + asks.getFirst().getPrice()) / 2;
            isResetting = false;
        }
    }


    synchronized public MarketSnapshot getMarketSnapshot(long time) {
        if (isResetting) {
            return null;
        }

        long invalidStateDuration = validator.getInvalidStateDurationInSeconds();
        if (invalidStateDuration >= 60 && (invalidStateDuration % 60 == 0)) {
            String msg = "Book " + name + " has been invalid for " + invalidStateDuration + " seconds.<br>";
            for (String errorMsg : validator.getErrors()) {
                msg += errorMsg + "<br>";
            }
            Dispatcher.getReporter().report(msg);
        }

        int balance = (int) Math.round((lowBalance + highBalance) / 2d);
        MarketSnapshot marketSnapshot = new MarketSnapshot(time, balance, midPointPrice);
        // reset values for the next market snapshot
        highBalance = lowBalance = lastBalance;

        return marketSnapshot;
    }


}
package com.jbooktrader.indicator.depth;

import com.jbooktrader.platform.indicator.*;

/**
 * Depth balance in the latest market snapshot.
 *  - Depth balance is defined as a relationship between the volume of all
 *    bids and all asks such that:
 *      100  -> Bids account for 100% of the total volume of bids and asks.
 *       0   -> The volume of bids equals the volume of asks.
 *     -100  -> Asks account for 100% of the total volume of bids and asks.	

 *    All bid/ask price levels are weighted equally. 
 *   
 */
public class DepthBalance extends Indicator {

    @Override
    public void calculate() {
        value = marketBook.getSnapshot().getBalance();
    }

    @Override
    public void reset() {
        calculate();
    }

}

Reply via email to