Classes Files

OrderBook/MamdaOrderBookPriceLevel.cs

Namespaces

Name
Wombat

Classes

  Name
class Wombat::MamdaOrderBookPriceLevel

Source code

/* $Id$
 *
 * OpenMAMA: The open middleware agnostic messaging API
 * Copyright (C) 2011 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
 */

using System;
using System.Collections;

namespace Wombat
{
    public class MamdaOrderBookPriceLevel : IEnumerable // IEnumerable<MamdaOrderBookEntry> if C# 2.0
    {
        public MamdaOrderBookPriceLevel()
        {
        }

        public MamdaOrderBookPriceLevel(MamdaOrderBookPriceLevel copy)
        {
            mPrice      = copy.mPrice;
            mSize       = copy.mSize;
            mSizeChange = copy.mSizeChange;
            mNumEntries = copy.mNumEntries;
            mSide       = copy.mSide;
            mAction     = copy.mAction;
            mTime       = copy.mTime;

            for (int i = 0; i < copy.mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = new MamdaOrderBookEntry(
                    (MamdaOrderBookEntry)copy.mEntries[i]);
                mEntries.Add(entry);
            }
        }

        public void copy(MamdaOrderBookPriceLevel copy)
        {
            setPrice(copy.mPrice);
            setSize(copy.mSize);
            setSizeChange(copy.mSizeChange);
            setNumEntries(copy.mNumEntries);
            setSide(copy.mSide);
            setAction(copy.mAction);
            setTime(copy.mTime); // always deep copied

            for (int i = 0; i < copy.mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                entry.copy((MamdaOrderBookEntry)copy.mEntries[i]);
                mEntries.Add(entry);
            }
        }

        public void setPrice(MamaPrice price)
        {
            if (mPrice == null)
            {
                if (price != null)
                {
                    mPrice = new MamaPrice(price); // copy
                }
            }
            else
            {
                if (price == null)
                {
                    mPrice.destroy();
                    mPrice = null;
                }
                else
                {
                    mPrice.copy(price);
                }
            }
        }

        public void setSize(long size)
        {
            mSize  = size;
        }

        public void setSizeChange(long size)
        {
            mSizeChange  = size;
        }

        public void setNumEntries(int numEntries)
        {
            mNumEntries = numEntries;
        }

        public void setSide(Sides side)
        {
            mSide  = side;
        }

        public void setAction(Actions action)
        {
            mAction = action;
        }

        public void setTime(DateTime time)
        {
            mTime = time;
        }

        public void setDetails(MamdaOrderBookPriceLevel level)
        {
            this.mSizeChange = level.mSize - this.mSize;
            this.mSize       = level.mSize;
            this.mNumEntries = level.mNumEntries;
            this.mTime       = level.mTime;
        }

        public void addEntry(MamdaOrderBookEntry  entry)
        {
            if (mStrictChecking)
            {
                checkNotExist(entry);
            }
            mEntries.Add(entry);
        }

        public void updateEntry(MamdaOrderBookEntry  entry)
        {
            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry existingEntry =
                    (MamdaOrderBookEntry)mEntries[i];
                if (existingEntry.equalId(entry.getId()))
                {
                    existingEntry.setDetails(entry);
                    return;
                }
            }
            if (mStrictChecking)
            {
                throw new MamdaOrderBookException(
                    "attempted to update a non-existent entry: " + entry.getId());
            }
        }

        public void removeEntry(MamdaOrderBookEntry  entry)
        {
            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry existingEntry =
                    (MamdaOrderBookEntry)mEntries[i];
                if (existingEntry.equalId(entry.getId()))
                {
                    mEntries.RemoveAt(i);
                    return;
                }
            }
            if (mStrictChecking)
            {
                throw new MamdaOrderBookException (
                    "attempted to delete a non-existent entry: " + entry.getId());
            }
        }

        public IEnumerator GetEnumerator()
        {
            return mEntries.GetEnumerator();
        }

        public void checkNotExist(MamdaOrderBookEntry  entry)
        {
            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry existingEntry =
                    (MamdaOrderBookEntry)mEntries[i];
                if (existingEntry.equalId(entry.getId()))
                {
                    throw new MamdaOrderBookException(
                        "attempted to add am existent entry: " + entry.getId());
                }
            }
        }

        public void markAllDeleted()
        {
            setSizeChange(-getSize());
            setSize(0);
            setNumEntries(0);
            setAction(Actions.Delete);

            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = (MamdaOrderBookEntry)mEntries[i];
                entry.setSize(0);
                entry.setAction(MamdaOrderBookEntry.Actions.Delete);
            }
        }

        public void setAsDifference(
            MamdaOrderBookPriceLevel lhs,
            MamdaOrderBookPriceLevel rhs)
        {
            int lhsBookSize = lhs.mEntries.Count;
            int rhsBookSize = rhs.mEntries.Count;
            int lhsIndex = 0;
            int rhsIndex = 0;

            while ((lhsIndex < lhsBookSize) && (rhsIndex < rhsBookSize))
            {
                string  lhsId                = null;
                string  rhsId                = null;
                long    lhsSize              = 0;
                long    rhsSize              = 0;
                MamdaOrderBookEntry lhsEntry = null;
                MamdaOrderBookEntry rhsEntry = null;

                if (lhsIndex < lhsBookSize)
                {
                    lhsEntry = (MamdaOrderBookEntry)lhs.mEntries[lhsIndex];
                    lhsId    = lhsEntry.getId();
                    lhsSize  = lhsEntry.getSize();
                }
                if (rhsIndex < rhsBookSize)
                {
                    rhsEntry = (MamdaOrderBookEntry)rhs.mEntries[rhsIndex];
                    rhsId    = rhsEntry.getId();
                    rhsSize  = rhsEntry.getSize();
                }

                if ((lhsId != null) && (rhsId != null))
                {
                    if (lhsId == rhsId)
                    {
                        // Same ID, maybe different size.
                        if (lhsSize != rhsSize)
                        {
                            MamdaOrderBookEntry updateEntry = new MamdaOrderBookEntry(rhsEntry);
                            updateEntry.setAction(MamdaOrderBookEntry.Actions.Update);
                            addEntry(updateEntry);
                        }
                        lhsIndex++;
                        rhsIndex++;
                        continue;
                    }
                    else
                    {
                        // Different ID (either something exists on the LHS
                        // and not on RHS or vice versa).
                        int rhsFound = findEntryAfter(rhs.mEntries, rhsIndex, lhsId);
                        if (rhsFound != rhsSize)
                        {
                            // The ID from the LHS was found on the RHS, so
                            // there must have been additional entries on the
                            // RHS, which we now need to add.
                            do
                            {
                                addEntry((MamdaOrderBookEntry)rhs.mEntries[rhsIndex]);
                                rhsIndex++;
                            }
                            while (rhsIndex < rhsFound);
                        }
                        else
                        {
                            // The ID from the LHS was not present on the RHS,
                            // so add the LHS entry.  Note: it would probably
                            // be faster to iterate over the LHS side rather
                            // than begin the loop again.
                            addEntry((MamdaOrderBookEntry)lhs.mEntries[lhsIndex]);
                            lhsIndex++;
                        }
                    }
                }
            }
            if (mPrice != null && rhs.getPrice() != null)
            {
                mPrice.destroy();
            }
            mPrice = rhs.getPrice();
            setSizeChange(rhs.getSize() - lhs.getSize());
            setSize(rhs.getSize());
            setNumEntries(rhs.getNumEntries());
            setAction(Actions.Update);
            mTime = rhs.getTime();
            setSide(rhs.getSide());
        }

        public MamaPrice getPrice()
        {
            return mPrice;
        }

        public long getSize()
        {
            return mSize;
        }

        public long getSizeChange()
        {
            return mSizeChange;
        }

        public int getNumEntries()
        {
            return mNumEntries;
        }

        public Sides getSide()
        {
            return mSide;
        }

        public Actions getAction ()
        {
            return mAction;
        }

        public bool hasTime()
        {
            return mTime != DateTime.MinValue;
        }

        public DateTime getTime ()
        {
            return mTime;
        }

        public void assertEqual(MamdaOrderBookPriceLevel  rhs)
        {
            if ((mPrice != null) != (rhs.mPrice != null))
                throwError("price not equal");
            if (!mPrice.equals(rhs.mPrice))
                throwError("price not equal");
            if (mSize != rhs.mSize)
                throwError("size not equal");
            if (mNumEntries != rhs.mNumEntries)
                throwError("number of entries not equal");
            if (mSide != rhs.mSide)
                throwError("side not equal");
            if (mAction != rhs.mAction)
                throwError("action not equal");
            if (mTime != rhs.mTime)
                throwError ("time not equal");

            if (mEntries.Count != rhs.mEntries.Count)
            {
                throwError ("entries size mismatch (" + mEntries.Count +
                    "!=" + rhs.mEntries.Count);
            }
            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry  lhsEntry = (MamdaOrderBookEntry)mEntries[i];
                MamdaOrderBookEntry  rhsEntry = (MamdaOrderBookEntry)rhs.mEntries[i];
                lhsEntry.assertEqual (rhsEntry);
            }
        }

        public static void setStrictChecking(bool strict)
        {
            mStrictChecking = strict;
        }

        public enum Actions : sbyte
        {
            Add     = (sbyte)'A',
            Update  = (sbyte)'U',
            Delete  = (sbyte)'D',
            Unknown = (sbyte)'Z'
        }

        public enum Sides : sbyte
        {
            Bid     = (sbyte)'B',
            Ask     = (sbyte)'A',
            Unknown = (sbyte)'U'
        }

        #region Implementation details

        private int findEntryAfter(
            ArrayList entries,
            int start,
            string id)
        {
            int i;
            int size = entries.Count;
            for (i = start; i < size; i++)
            {
                MamdaOrderBookEntry entry = (MamdaOrderBookEntry)entries[i];
                if (entry.equalId(id))
                {
                    return i;
                }
            }
            return i;
        }

        private void throwError(string context)
        {
            throw new MamdaOrderBookException(context + "(price=" + mPrice +
                ", size=" + mSide);
        }

        private MamaPrice    mPrice      = null;
        private long         mSize       = 0;
        private long         mSizeChange = 0;
        private int          mNumEntries = 0;
        private Sides        mSide       = Sides.Unknown;
        private Actions      mAction     = Actions.Unknown;
        private DateTime     mTime       = DateTime.MinValue;
        private ArrayList    mEntries    = new ArrayList();

        private static bool mStrictChecking = false;

        #endregion Implementation details

    }
}

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