Ejemplo n.º 1
0
def test_failed_instantiation_products_not_the_same():
    market1 = Market(Product("MSFT", "Microsoft"), Endpoint("Nasdaq", "NSDQ"),
                     PriceFactory(".01"))
    market2 = Market(Product("APPL", "Apple"), Endpoint("Nasdaq", "NSDQ"),
                     PriceFactory(".01"))
    bid_quote = Quote(market1, BID_SIDE, "25.23", 18)
    ask_quote = Quote(market2, ASK_SIDE, "26.20", 233)
    with pytest.raises(Exception):
        TwoSidedQuote(bid_quote, ask_quote)
Ejemplo n.º 2
0
def test_failed_set_sell_quote_wrong_product():
    market1 = Market(Product("MSFT", "Microsoft"), Endpoint("Nasdaq", "NSDQ"),
                     PriceFactory("0.01"))
    market2 = Market(Product("APPL", "Apple"), Endpoint("Nasdaq", "NSDQ"),
                     PriceFactory("0.01"))
    bid_quote = Quote(market1, BID_SIDE, "25.23", 18)
    ask_quote = Quote(market1, ASK_SIDE, "26.20", 233)
    ask_quote2 = Quote(market2, ASK_SIDE, "25.98", 3)
    tsq = TwoSidedQuote(bid_quote, ask_quote)
    with pytest.raises(Exception):
        tsq.set_sell_quote(ask_quote2)
Ejemplo n.º 3
0
def test_get_price():
    pf = PriceFactory("0.01")
    p = pf.get_price(100)
    assert p == Price(100)
    assert p == Decimal("100.00")
    p = pf.get_price("100.01")
    assert p == Price("100.01")
    assert p == Decimal("100.01")
    p = pf.get_price(Decimal("222.22"))
    assert p == Price("222.22")
    assert p == Decimal("222.22")
Ejemplo n.º 4
0
def test_equality():
    q1 = Quote(MARKET, BID_SIDE, Price("95.42"), 94)
    q2 = Quote(MARKET, BID_SIDE, Price("95.42"), 94)
    assert q1 == q2

    q2 = Quote(
        Market(Product("APPL", "Apple"), Endpoint("Nasdaq", "NSDQ"),
               PriceFactory("0.01")), BID_SIDE, Price("95.42"), 94)
    assert q1 != q2

    q2 = Quote(MARKET, BID_SIDE, Price("95.43"), 94)
    assert q1 != q2

    q2 = Quote(MARKET, BID_SIDE, Price("95.42"), 91)
    assert q1 != q2

    q2 = Quote(MARKET, BID_SIDE, Price("95.42"), 94, 2)
    assert q1 != q2

    q2 = Quote(MARKET, BID_SIDE, Price("95.42"), 94, 0)
    assert q1 == q2

    q1 = Quote(MARKET, BID_SIDE, Price("95.42"), 94, 3)
    q2 = Quote(MARKET, BID_SIDE, Price("95.42"), 94, 3)
    assert q1 == q2
Ejemplo n.º 5
0
def test_prev_price():
    pf = PriceFactory(".5")
    starting_price = pf.get_price(100)
    new_price = pf.prev_price(starting_price, BID_SIDE)
    assert new_price == Price("99.5")
    new_price = pf.prev_price(new_price, BID_SIDE)
    assert new_price == Price(99)

    new_price = pf.prev_price(new_price, ASK_SIDE)
    assert new_price == Price("99.5")
    new_price = pf.prev_price(new_price, ASK_SIDE)
    assert new_price == Price(100)
Ejemplo n.º 6
0
def test_next_price():
    pf = PriceFactory(".5")
    starting_price = pf.get_price(100)
    new_price = pf.next_price(starting_price, BID_SIDE)
    assert new_price == Price("100.5")
    new_price = pf.next_price(new_price, BID_SIDE)
    assert new_price == Price(101)

    new_price = pf.next_price(new_price, ASK_SIDE)
    assert new_price == Price("100.5")
    new_price = pf.next_price(new_price, ASK_SIDE)
    assert new_price == Price(100)
Ejemplo n.º 7
0
def test_price_validation():
    p = Price("23.455")
    pf = PriceFactory("0.01")
    assert pf.is_valid_price(p) is False

    p = Price("23.45")
    pf = PriceFactory("0.01")
    assert pf.is_valid_price(p)

    p = Price("23.455")
    pf = PriceFactory("0.001")
    assert pf.is_valid_price(p)

    p = Price("23.45")
    pf = PriceFactory("0.1")
    assert pf.is_valid_price(p) is False

    p = Price("23.45")
    pf = PriceFactory(".5")
    assert pf.is_valid_price(p) is False
Ejemplo n.º 8
0
def test_to_str():
    # doesn't really do anything, just makes sure no issues with getting the str
    str(
        PriceFactory("0.01",
                     min_price=Decimal("0.0"),
                     max_price=Decimal("100.0")))
Ejemplo n.º 9
0
def test_to_json():
    # doesn't really do anything, just makes sure no issues with getting the json
    json.dumps(
        PriceFactory("0.01",
                     min_price=Decimal("0.0"),
                     max_price=Decimal("100.0")).to_json())
Ejemplo n.º 10
0
def test_max_price_excpetion():
    with pytest.raises(InvalidPriceException):
        pf = PriceFactory("0.01", max_price=Decimal("100.0"))
        pf.get_price("100.01")
Ejemplo n.º 11
0
from buttonwood.MarketObjects.Events.OrderEvents import CancelCommand
from buttonwood.MarketObjects.Events.OrderEvents import CancelReplaceCommand
from buttonwood.MarketObjects.Events.OrderEvents import CancelReport
from buttonwood.MarketObjects.Events.OrderEvents import FullFillReport
from buttonwood.MarketObjects.Events.OrderEvents import NewOrderCommand
from buttonwood.MarketObjects.Events.OrderEvents import PartialFillReport
from buttonwood.MarketObjects.Endpoint import Endpoint
from buttonwood.MarketObjects.Market import Market
from buttonwood.MarketObjects.Price import Price
from buttonwood.MarketObjects.Price import PriceFactory
from buttonwood.MarketObjects.Product import Product
from buttonwood.MarketObjects.Side import BID_SIDE, ASK_SIDE
from buttonwood.utils.IDGenerators import MonotonicIntID


MARKET = Market(Product("MSFT", "Microsoft"), Endpoint("Nasdaq", "NSDQ"), PriceFactory("0.01"))

LOGGER = logging.getLogger()


def test_exposure():
    e1 = Exposure(Price("1.1"), 2, 12345)
    e2 = Exposure(Price("1.1"), 2, 12345)
    assert e1 == e2
    assert e1.equivalent_exposure(e2)
    assert e1.equivalent_exposure(e1)
    assert e2.equivalent_exposure(e1)
    e3 = Exposure(Price("1.1"), 2, 6789)
    assert e1 != e3
    assert e1.price() == e2.price()
    print(e1, e2)
Ejemplo n.º 12
0
def test_get_price_wrong_mpi_int():
    with pytest.raises(InvalidPriceException):
        pf = PriceFactory(5)
        pf.get_price(7)
Ejemplo n.º 13
0
def test_min_price_excpetion():
    with pytest.raises(InvalidPriceException):
        pf = PriceFactory("0.01", min_price=Decimal("100.0"))
        # should work for 100.01 and 100.0 but not 99.99
        # also, price 100.01 should and 100.00 should not create 99.00
        pf.get_price("99.99")
Ejemplo n.º 14
0
SOFTWARE.
"""

import json
import sys
from decimal import Decimal
from buttonwood.MarketObjects.Endpoint import Endpoint
from buttonwood.MarketObjects.Product import Product
from buttonwood.MarketObjects.Price import Price
from buttonwood.MarketObjects.Price import PriceFactory
from buttonwood.MarketObjects.Market import Market
from buttonwood.MarketObjects.Price import InvalidPriceException

PRODUCT = Product("AAA", "Some Product named AAA")
ENDPOINT = Endpoint("GenMatch", "Generic matching venue")
PRICE_FACTORY = PriceFactory(Decimal("0.01"))


def test_default_market_creation():
    mrkt = Market(PRODUCT, ENDPOINT, PRICE_FACTORY)
    assert PRODUCT == mrkt.product()
    assert ENDPOINT == mrkt.endpoint()
    assert mrkt.min_price_increment() == mrkt.mpi() == Decimal("0.01")
    assert mrkt.min_qty() == 1
    assert mrkt.qty_increment() == 1
    assert mrkt.max_qty() == sys.maxsize


def test_market_creation():
    mrkt = Market(PRODUCT, ENDPOINT, PRICE_FACTORY, min_qty=2, qty_increment=4)
    assert PRODUCT == mrkt.product()
Ejemplo n.º 15
0
"""

import pytest
from buttonwood.MarketObjects.Events.OrderEventConstants import *
from buttonwood.MarketObjects.Events.OrderEvents import NewOrderCommand
from buttonwood.MarketObjects.Endpoint import Endpoint
from buttonwood.MarketObjects.Market import Market
from buttonwood.MarketObjects.Price import Price
from buttonwood.MarketObjects.Price import PriceFactory
from buttonwood.MarketObjects.Product import Product
from buttonwood.MarketObjects.Side import BID_SIDE
from buttonwood.MarketObjects.Events.OrderEventConstants import MARKET as MARKET_ORDER
from buttonwood.MarketObjects.Events.OrderEventConstants import LIMIT as LIMIT_ORDER

MARKET = Market(Product("MSFT", "Microsoft"), Endpoint("Nasdaq", "NSDQ"),
                PriceFactory("0.01"))


def test_creation():
    new_order = NewOrderCommand(12, 324893458.324313, "342adf24441", "user_x",
                                MARKET, BID_SIDE, FAK, Price("23.01"), 234, 2)
    assert new_order.event_type_str() == "New Order Command"
    assert new_order.price() == Price("23.01")
    assert new_order.market() == MARKET
    assert new_order.user_id() == "user_x"
    assert new_order.timestamp() == 324893458.324313
    assert new_order.event_id() == 12
    assert new_order.side() == BID_SIDE
    assert new_order.qty() == 234
    assert new_order.iceberg_peak_qty() == 2
Ejemplo n.º 16
0
def test_get_price_wrong_mpi_decimal():
    with pytest.raises(InvalidPriceException):
        pf = PriceFactory("0.01")
        pf.get_price(Decimal("100.001"))
Ejemplo n.º 17
0
def test_max_price():
    pf = PriceFactory("0.01", max_price=Decimal("100.0"))
    # should work for 99.99 and 100.0 but not 100.01
    # also, price 99.99 and 100.00 should be created, but should not create 99.00
    pf.get_price("99.99")
    pf.get_price("100.00")
Ejemplo n.º 18
0
def test_min_price():
    pf = PriceFactory("0.01", min_price=Decimal("100.0"))
    # should work for 100.01 and 100.0 but not 99.99
    # also, price 100.01 should and 100.00 should not create 99.00
    pf.get_price("100.01")
    pf.get_price("100.00")
Ejemplo n.º 19
0
def get_events():
    # set up a Market for the events. For that you need at least:
    #  1) the Product
    #  2) the Endpoint
    #  3) the PriceFactory
    prod = Product("AAAA", "Test Product")
    ep = Endpoint("Exchange 1", "EXC1")
    pf = PriceFactory(
        "0.01"
    )  # pricefactory needs the minimum price increment, which is 0.01 for this example
    market = Market(prod, ep, pf)

    # now create a mapping of what we'll parse out of the file to the Market.
    # This comes in even more handy when there are multiple markets
    mrkt_dict = {("AAAA", "EXC1"): market}

    # set up the time stamp parser
    time_stamp_frmt = "%Y-%m-%d %H:%M:%S.%f"

    # we are going to keep a dictionary of event_id to Command so that we can properly create Execution Reports
    id_to_cmd = {}

    created_events = []

    # first we need to parse each line
    for line in EXAMPLE_DATA:
        parts = line[:-1].split(',')
        # skip header
        if parts[0] == "Order ID":
            continue

        # Order Id is the unique identifier of the order chain
        chain_id = parts[0]
        # Index is the unique identifier of the event
        event_id = int(parts[1])
        # Need an identifier of the user that placed the order
        user = parts[7]

        # get the event time
        event_time = datetime.strptime(parts[3], time_stamp_frmt)
        # Event objects what the time stamp as a float (seconds.microseconds) so convert to time since epoch
        time_stamp = datetime_to_epoch(event_time)

        # now get the market
        prod_name = parts[4]
        ep_name = parts[5]
        mrkt = mrkt_dict[(prod_name, ep_name)]

        # get the side: not all events contain side so default is None.
        # Buttonwood provides a helper that converts the most common str representations of Buy & Sell to Side objects
        side = Side.get_side(parts[8])

        # get the time in force. Not all events need time in force so the default is None.
        # Note: could have used OrderEventContants.TIME_IN_FORCE_STR_TO_INT here but wanted to show a more extensive use
        #   of the constants
        if parts[6] == "FAR":
            tif = OrderEventConstants.FAR
        elif parts[6] == "FAK":
            tif = OrderEventConstants.FAK
        elif parts[6] == "FOK":
            tif = OrderEventConstants.FOK
        elif parts[6] == "":
            tif = None
        else:
            raise Exception("Could not convert %s to a known TimeInForce" %
                            parts[6])

        # get event type so we can create the right events
        event_type = parts[2]

        if event_type == "New":  # for event type "New" create a new event
            # get price, using Market's get_price function that will gets a Price object for a string, Decimal, or int
            price = mrkt.get_price(parts[9])
            qty = int(parts[10])
            event = NewOrderCommand(event_id, time_stamp, chain_id, user,
                                    market, side, tif, price, qty)
            # add the event to the event id to command dictionary
            id_to_cmd[event_id] = event
        elif event_type == "Mod":  # for event type "Mod" create a cancel replace event
            # get price, using Market's get_price function that will gets a Price object for a string, Decimal, or int
            price = mrkt.get_price(parts[9])
            qty = int(parts[10])
            event = CancelReplaceCommand(event_id, time_stamp, chain_id, user,
                                         market, side, price, qty)
            # add the event to the event id to command dictionary
            id_to_cmd[event_id] = event
        elif event_type == "Cancel":  # for event type "Cancel" create a Cancel command event
            # there can be different types of cancels, but in this case we are assuming it is a user requested cancel
            cancel_type = CancelReasons.USER_CANCEL
            event = CancelCommand(event_id, time_stamp, chain_id, user, market,
                                  cancel_type)
            # add the event to the event id to command dictionary
            id_to_cmd[event_id] = event
        elif event_type == "Ack":  # for event type "Ack" create an Acknowledgement
            # this example file has no concept of iceberg orders so iceberg_peak is None (which will cause buttonwood to
            #  to treat the entire order qty as an iceberg
            iceberg_peak = None
            # get price, using Market's get_price function that gets a Price object for a string, Decimal, or int
            price = mrkt.get_price(parts[9])
            qty = int(parts[10])
            # response to command is the command it is acknowledging, get that ID and look it up from our id_to_cmd dict
            response_to_id = int(parts[12])
            response_to_cmd = id_to_cmd[response_to_id]
            event = AcknowledgementReport(event_id, time_stamp, chain_id, user,
                                          market, response_to_cmd, price, qty,
                                          iceberg_peak)
        elif event_type == "Cancel Conf":  # for event type "Cancel Conf" create a Cancel report event
            # get the cancel reason
            if parts[15] == "FOK Miss":
                reason = CancelReasons.FOK_CANCEL
            elif parts[15] == "Requested":
                reason = CancelReasons.USER_REQUESTED
            else:
                raise Exception("Could not convert %s to a cancel reason." %
                                parts[15])
            # cancel command is the command that caused the cancel, get that ID and look it up from our id_to_cmd dict
            response_to_id = int(parts[12])
            response_to_cmd = id_to_cmd[response_to_id]
            event = CancelReport(event_id, time_stamp, chain_id, user, market,
                                 response_to_cmd, reason)
        elif event_type == "Part Fill":  # if event type "Part Fill" create a Partial Fill event
            # the aggressing command comes from getting the id and looking it up in the id to cmd dict
            aggressing_id = int(parts[13])
            aggressing_cmd = id_to_cmd[aggressing_id]
            # get fill price, using Market's get_price function that gets a Price object for a string, Decimal, or int
            fill_price = mrkt.get_price(parts[9])
            fill_qty = int(parts[10])
            # get leaves qty from the file
            leaves_qty = int(parts[11])
            # get the match_id from the file
            match_id = parts[14]
            event = PartialFillReport(event_id, time_stamp, chain_id, user,
                                      market, aggressing_cmd, fill_qty,
                                      fill_price, side, match_id, leaves_qty)
        elif event_type == "Full Fill":  # if event type "Full Fill" create a Partial Fill event
            # the aggressing command comes from getting the id and looking it up in the id to cmd dict
            aggressing_id = int(parts[13])
            aggressing_cmd = id_to_cmd[aggressing_id]
            # get fill price, using Market's get_price function that gets a Price object for a string, Decimal, or int
            fill_price = mrkt.get_price(parts[9])
            fill_qty = int(parts[10])
            # full fills don't need/have a leaves qty because nothing is left.
            # get the match_id from the file
            match_id = parts[14]
            event = FullFillReport(event_id, time_stamp, chain_id, user,
                                   market, aggressing_cmd, fill_qty,
                                   fill_price, side, match_id)
        else:
            raise Exception("Could not convert %s to an Event" % event_type)

        created_events.append(event)
    return created_events