Classes Files

options/MamdaOptionChain.java

Namespaces

Name
com::wombat::mamda::options

Classes

  Name
class com::wombat::mamda::options::MamdaOptionChain

Source code

/* $Id$
 *
 * OpenMAMA: The open middleware agnostic messaging API
 * Copyright (C) 2012 NYSE Technologies, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

package com.wombat.mamda.options;

import com.wombat.mamda.*;
import java.util.logging.*;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.HashMap;
import java.util.SortedSet;
import java.util.Collection;

public class MamdaOptionChain
{
    private String                 mSymbol             = null;
    private MamdaQuoteListener     mQuoteListener      = null;
    private MamdaTradeListener     mTradeListener      = null;

    private final HashMap          mOptions            = new HashMap (1000);
    private final TreeSet          mCallOptions        = new TreeSet (new ContractComparator());
    private final TreeSet          mPutOptions         = new TreeSet (new ContractComparator());
    private final TreeSet          mExchanges          = new TreeSet ();
    private final TreeSet          mStrikePrices       = new TreeSet ();
    private final MamdaOptionExpirationDateSet mExpirationSet =
        new MamdaOptionExpirationDateSet();

    private static Logger mLogger = Logger.getLogger (
        "com.wombat.mamda.options.MamdaOptionChain");

    public MamdaOptionChain (String symbol)
    {
        setSymbol (symbol);
    }

    public void setSymbol (String symbol)
    {
        mSymbol = symbol;
    }

    public String getSymbol ()
    {
        return mSymbol;
    }

    public void setUnderlyingQuoteListener (
        MamdaQuoteListener  quoteListener)
    {
        mQuoteListener = quoteListener;
    }

    public void setUnderlyingTradeListener (
        MamdaTradeListener  tradeListener)
    {
        mTradeListener = tradeListener;
    }

    public MamdaQuoteListener  getUnderlyingQuoteListener ()
    {
        return mQuoteListener;
    }

    public MamdaTradeListener  getUnderlyingTradeListener ()
    {
        return mTradeListener;
    }

    public MamdaOptionContract getContract (String contractSymbol)
    {
        return (MamdaOptionContract) mOptions.get(contractSymbol);
    }

    public SortedSet getExchanges()
    {
        return mExchanges;
    }

    public SortedSet getStrikePrices()
    {
        return mStrikePrices;
    }

    public void addContract (String               contractSymbol,
                             MamdaOptionContract  contract)
    {
        Date   expireDate  = contract.getExpireDate();
        Double strikePrice = new Double(contract.getStrikePrice());
        String exchange    = contract.getExchange();
        char   putCall     = contract.getPutCall();

        mLogger.fine ("adding contract: " + contractSymbol + " " + 
                       exchange + " " + strikePrice);
        mOptions.put (contractSymbol, contract);

        if (contract.getPutCall() == MamdaOptionContract.PC_CALL)
        {
            mCallOptions.add (contract);
        }
        else
        {
            mPutOptions.add (contract);
        }

        // Add the contract to the expiration-by-strike set.
        MamdaOptionExpirationStrikes expireStrikes =
            (MamdaOptionExpirationStrikes) mExpirationSet.get (expireDate);

        if (expireStrikes == null)
        {
            expireStrikes = new MamdaOptionExpirationStrikes();
            mExpirationSet.put (expireDate, expireStrikes);
        }

        MamdaOptionStrikeSet strikeSet =
            (MamdaOptionStrikeSet) expireStrikes.get (strikePrice);

        if (strikeSet == null)
        {
            strikeSet = new MamdaOptionStrikeSet (expireDate,
                                                  strikePrice.doubleValue());
            expireStrikes.put (strikePrice, strikeSet);
        }

        MamdaOptionContractSet contractSet =
            (putCall == MamdaOptionContract.PC_CALL) ?
                strikeSet.getCallSet() : strikeSet.getPutSet();

        if (MamdaOptionExchangeUtils.isBbo(exchange))
        {
            contractSet.setBboContract (contract);
        }
        else if (MamdaOptionExchangeUtils.isWombatBbo(exchange))
        {
            contractSet.setWombatBboContract (contract);
        }
        else
        {
            contractSet.setExchangeContract (exchange, contract);
            mExchanges.add (exchange);
        }

        mStrikePrices.add (strikePrice);
        mLogger.fine ("number of expirations: " + mExpirationSet.size());
    }

    public void removeContract (String contractSymbol) 
    {
    }

    public double getAtTheMoney (
        short  compareType)
    {
        double atTheMoney = 0.0;
        switch (compareType)
        {
            case MamdaOptionAtTheMoneyCompareType.MID_QUOTE:
                if (mQuoteListener == null) return 0.0;
                atTheMoney = (mQuoteListener.getBidPrice().getValue() +
                              mQuoteListener.getAskPrice().getValue()) / 2.0;
                break;

            case MamdaOptionAtTheMoneyCompareType.BID:
                if (mQuoteListener == null) return 0.0;
                atTheMoney = mQuoteListener.getBidPrice().getValue();
                break;

            case MamdaOptionAtTheMoneyCompareType.ASK:
                if (mQuoteListener == null) return 0.0;
                atTheMoney = mQuoteListener.getAskPrice().getValue();
                break;

            case MamdaOptionAtTheMoneyCompareType.LAST_TRADE:
                if (mTradeListener == null) return 0.0;
                atTheMoney = mTradeListener.getLastPrice().getValue();
                break;
        }
        return atTheMoney;
    }

    public boolean getIsPriceWithinPercentOfMoney (
        double    price,
        double    percentage,
        short     compareType)
    {
        double atTheMoney  = getAtTheMoney(compareType);
        if (atTheMoney == 0.0)
            return false;

        return (((1.0 - percentage) <= price) ||
                (price <= (1.0 + percentage)));
    }

    public SortedSet getStrikesWithinPercent (
        double    percentage,
        short     compareType)
    {
        percentage /= 100.0;
        if (percentage <= 0.0)
            return null;

        double atTheMoney  = getAtTheMoney(compareType);
        if (atTheMoney == 0.0)
            return null;

        Double    lowPercent   = new Double (atTheMoney * (1.0 - percentage));
        Double    highPercent  = new Double (atTheMoney * (1.0 + percentage));
        SortedSet strikeSubSet = mStrikePrices.subSet (lowPercent,
                                                       highPercent);
        return strikeSubSet;
    }

    public SortedSet getStrikesWithinRangeSize (
        int       rangeLength,
        short     compareType)
    {
        if (rangeLength <= 0)
            return null;

        double atTheMoney  = getAtTheMoney(compareType);
        if (atTheMoney == 0.0)
            return null;

        int     countToMoney    = 0;
        int     countFromMoney  = 0;
        double  halfRangeLength = rangeLength / 2.0;
        Double  lowerBound      = null;
        Double  upperBound      = null;

        // First loop determines the upper bound and count the number
        // of strikes that are less than the "money".
        Iterator strikeIter = mStrikePrices.iterator();
        while (strikeIter.hasNext())
        {
            Double strikePrice = (Double) strikeIter.next();
            if (strikePrice.doubleValue() < atTheMoney)
            {
                // We're still less than the "money", so keep counting up.
                countToMoney++;
            }
            else
            {
                // Check the upper bound. Take a price that is
                // slightly higher than this strike price because we
                // want to include it (Set.subSet excludes the
                // toElement).
                countFromMoney++;
                upperBound = new Double(strikePrice.doubleValue()+0.00001);
                if (countFromMoney >= halfRangeLength)
                {
                    // We've passed the upper end of the range
                    break;
                }
            }
        }

        // Second loop determines the lower bound.
        int targetCount = countToMoney - (rangeLength - countFromMoney);
        strikeIter = mStrikePrices.iterator();
        while (strikeIter.hasNext())
        {
            Double strikePrice = (Double) strikeIter.next();
            if (targetCount > 0)
            {
                // We have not yet hit the lowerBound.
                targetCount--;
            }
            else
            {
                lowerBound = strikePrice;
                break;
            }
        }
        if (lowerBound == null)
            lowerBound = new Double(0.0);
        if (upperBound == null)
            upperBound = new Double(Double.MAX_VALUE);

        SortedSet result = mStrikePrices.subSet(lowerBound,upperBound);
        lowerBound = (Double) result.first();
        upperBound = (Double) result.last();
        mLogger.finer ("getStrikesWithinRangeSize: lowerBound=" + lowerBound +
                       " atTheMoney=" + atTheMoney +
                       " upperBound=" + upperBound);
        return result;
    }

    public Iterator callIterator()
    {
        return mCallOptions.iterator();
    }

    public Iterator putIterator()
    {
        return mPutOptions.iterator();
    }

    public MamdaOptionExpirationDateSet getAllExpirations ()
    {
        return mExpirationSet;
    }

    public void dump ()
    {
        System.out.println ("Dump chain: " + mSymbol);

        int      i        = 0;
        Iterator callIter = mCallOptions.iterator();
        Iterator putIter  = mPutOptions.iterator();

        while (callIter.hasNext() || putIter.hasNext())
        {
            System.out.print ("" + i + " | ");
            if (callIter.hasNext())
            {
                MamdaOptionContract callContract =
                    (MamdaOptionContract)callIter.next();
                System.out.print ("" + callContract.getSymbol() + " " +
                                  callContract.getExchange() + "   " +
                                  callContract.getExpireDate() + "   " +
                                  callContract.getStrikePrice());
            }
            else
            {
                System.out.print ("          ");
            }

            System.out.print (" | ");

            if (putIter.hasNext())
            {
                MamdaOptionContract putContract =
                    (MamdaOptionContract)putIter.next();
                System.out.print ("" + putContract.getSymbol() + " " +
                                  putContract.getExchange() + "   " +
                                  putContract.getExpireDate() + "   " +
                                  putContract.getStrikePrice());
            }
            else
            {
            }
            System.out.println();
            ++i;
        }
    }

    private class ContractComparator implements Comparator
    {
        /* Ascending expiration month, strike price, and exchange. */
        public int compare (Object o1, Object o2)
        {
            MamdaOptionContract contract1 = (MamdaOptionContract)o1;
            MamdaOptionContract contract2 = (MamdaOptionContract)o2;

            // Expiration month
            Date expiration1 = contract1.getExpireDate();
            Date expiration2 = contract2.getExpireDate();
            int comp = expiration1.compareTo(expiration2);
            if (comp == 0)
            {
                // Strike price
                Double strike1 = new Double(contract1.getStrikePrice());
                Double strike2 = new Double(contract2.getStrikePrice());
                comp = strike1.compareTo(strike2);
            }
            if (comp == 0)
            {
                // Exchange
                String exchange1 = contract1.getExchange();
                String exchange2 = contract2.getExchange();
                comp = exchange1.compareTo(exchange2);
            }
            return comp;
        }
        public boolean equals (Object o1, Object o2)
        { 
            return (compare(o1,o2) == 0);
        }
    }
}

Updated on 2023-03-31 at 15:30:39 +0100