diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index e6a7df4..f7bed23 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ "3.10", "3.11", "3.12" ] + python-version: [ "3.10", "3.11", "3.12", "3.13" ] steps: - name: Check out repository code uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 73a8015..01e29c4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ benchmark_history.svg __pycache__/ venv/ site/ +docs/reference/ *.egg-info .coverage diff --git a/README.md b/README.md index 7bb3222..59b2060 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ pip install order-matching ## Usage ```python +>>> from datetime import datetime, timedelta >>> from pprint import pp >>> import pandas as pd @@ -37,8 +38,8 @@ pip install order-matching >>> from order_matching.orders import Orders >>> matching_engine = MatchingEngine(seed=123) ->>> timestamp = pd.Timestamp("2023-01-01") ->>> transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") +>>> timestamp = datetime(2023, 1, 1) +>>> transaction_timestamp = timestamp + timedelta(days=1) >>> buy_order = LimitOrder(side=Side.BUY, price=1.2, size=2.3, timestamp=timestamp, order_id="a", trader_id="x") >>> sell_order = LimitOrder(side=Side.SELL, price=0.8, size=1.6, timestamp=timestamp, order_id="b", trader_id="y") >>> executed_trades = matching_engine.match(orders=Orders([buy_order, sell_order]), timestamp=transaction_timestamp) @@ -51,7 +52,7 @@ pip install order-matching book_order_id='a', execution=LIMIT, trade_id='c4da537c-1651-4dae-8486-7db30d67b366', - timestamp=Timestamp('2023-01-02 00:00:00'))] + timestamp=datetime.datetime(2023, 1, 2, 0, 0))] ``` diff --git a/mkdocs.yaml b/mkdocs.yml similarity index 100% rename from mkdocs.yaml rename to mkdocs.yml diff --git a/pyproject.toml b/pyproject.toml index 7d150d7..3de68c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] requires-python = ">=3.10" dependencies = ["pandas", "pandera", "faker"] @@ -21,6 +22,9 @@ dependencies = ["pandas", "pandera", "faker"] Source = "https://github.com/khrapovs/OrderBookMatchingEngine" Documentation = "https://order-book-matching-engine.readthedocs.io/" +[tool.uv] +default-groups = ["dev", "test", "doc"] + [dependency-groups] test = ["pytest", "pytest-cov", "pytest-xdist", "pytest-benchmark[histogram]"] doc = [ diff --git a/src/order_matching/executed_trades.py b/src/order_matching/executed_trades.py index bf72a12..b7d887d 100644 --- a/src/order_matching/executed_trades.py +++ b/src/order_matching/executed_trades.py @@ -2,6 +2,7 @@ from collections import defaultdict from dataclasses import asdict +from datetime import datetime import pandas as pd from pandera.typing import DataFrame @@ -22,7 +23,7 @@ class ExecutedTrades: """ def __init__(self, trades: list[Trade] | None = None) -> None: - self._trades: dict[pd.Timestamp, list[Trade]] = defaultdict(list) + self._trades: dict[datetime, list[Trade]] = defaultdict(list) if trades: self.add(trades=trades) @@ -45,7 +46,7 @@ def add(self, trades: list[Trade]) -> None: for trade in trades: self._trades[trade.timestamp].append(trade) - def get(self, timestamp: pd.Timestamp) -> list[Trade]: + def get(self, timestamp: datetime) -> list[Trade]: """Get subset by timestamp. Returns diff --git a/src/order_matching/matching_engine.py b/src/order_matching/matching_engine.py index 25e2a1c..3befa84 100644 --- a/src/order_matching/matching_engine.py +++ b/src/order_matching/matching_engine.py @@ -1,4 +1,4 @@ -import pandas as pd +from datetime import datetime from order_matching.executed_trades import ExecutedTrades from order_matching.order import Order @@ -19,13 +19,14 @@ class MatchingEngine: Examples -------- + >>> from datetime import datetime, timedelta >>> from pprint import pp >>> from order_matching.matching_engine import MatchingEngine >>> from order_matching.order import LimitOrder >>> from order_matching.side import Side >>> matching_engine = MatchingEngine(seed=123) - >>> timestamp = pd.Timestamp("2023-01-01") - >>> transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + >>> timestamp = datetime(2023, 1, 1) + >>> transaction_timestamp = timestamp + timedelta(days=1) >>> buy_order = LimitOrder(side=Side.BUY, price=1.2, size=2.3, timestamp=timestamp, order_id="a", trader_id="x") >>> sell_order = LimitOrder(side=Side.SELL, price=0.8, size=1.6, timestamp=timestamp, order_id="b", trader_id="y") >>> executed_trades = matching_engine.match(orders=Orders([buy_order, sell_order]), timestamp=transaction_timestamp) @@ -37,7 +38,7 @@ class MatchingEngine: book_order_id='a', execution=LIMIT, trade_id='c4da537c-1651-4dae-8486-7db30d67b366', - timestamp=Timestamp('2023-01-02 00:00:00'))] + timestamp=datetime.datetime(2023, 1, 2, 0, 0))] """ def __init__(self, seed: int | None = None) -> None: @@ -45,9 +46,9 @@ def __init__(self, seed: int | None = None) -> None: self._faker = get_faker(seed=seed) self._queue = Orders() self.unprocessed_orders = OrderBook() - self._timestamp: pd.Timestamp | None = None + self._timestamp: datetime - def match(self, timestamp: pd.Timestamp, orders: Orders | None = None) -> ExecutedTrades: + def match(self, timestamp: datetime, orders: Orders | None = None) -> ExecutedTrades: """Match incoming orders in price-time priority. Parameters diff --git a/src/order_matching/order.py b/src/order_matching/order.py index 2738047..a8420b9 100644 --- a/src/order_matching/order.py +++ b/src/order_matching/order.py @@ -1,6 +1,5 @@ from dataclasses import dataclass, field - -import pandas as pd +from datetime import datetime from order_matching.execution import Execution from order_matching.side import Side @@ -14,11 +13,11 @@ class Order: side: Side price: float size: float - timestamp: pd.Timestamp + timestamp: datetime order_id: str trader_id: str execution: Execution - expiration: pd.Timestamp = pd.NaT + expiration: datetime = datetime.max status: Status = Status.OPEN price_number_of_digits: int = 1 diff --git a/src/order_matching/order_book.py b/src/order_matching/order_book.py index 5d0226f..ac8fdfc 100644 --- a/src/order_matching/order_book.py +++ b/src/order_matching/order_book.py @@ -1,4 +1,5 @@ from collections import defaultdict +from datetime import datetime from typing import cast import pandas as pd @@ -18,7 +19,7 @@ class OrderBook: def __init__(self) -> None: self.bids: OrderBookOrdersType = defaultdict(Orders) self.offers: OrderBookOrdersType = defaultdict(Orders) - self.orders_by_expiration: dict[pd.Timestamp, Orders] = defaultdict(Orders) + self.orders_by_expiration: dict[datetime, Orders] = defaultdict(Orders) def append(self, incoming_order: Order) -> None: """Add one order to the order book. @@ -101,7 +102,7 @@ def get_opposite_side_orders(self, incoming_order: Order) -> OrderBookOrdersType case Side.BUY: return self.offers - def get_subset(self, expiration: pd.Timestamp) -> Orders: + def get_subset(self, expiration: datetime) -> Orders: """Get orders with given expiration time. Parameters diff --git a/src/order_matching/orders.py b/src/order_matching/orders.py index a7ff507..96d7043 100644 --- a/src/order_matching/orders.py +++ b/src/order_matching/orders.py @@ -70,6 +70,12 @@ def to_frame(self) -> DataFrame[OrderDataSchema]: OrderDataSchema.side: lambda df: df[OrderDataSchema.side].astype(str), OrderDataSchema.execution: lambda df: df[OrderDataSchema.execution].astype(str), OrderDataSchema.status: lambda df: df[OrderDataSchema.status].astype(str), + OrderDataSchema.timestamp: lambda df: pd.to_datetime( + df[OrderDataSchema.timestamp], errors="coerce" + ), + OrderDataSchema.expiration: lambda df: pd.to_datetime( + df[OrderDataSchema.expiration], errors="coerce" + ), } ) diff --git a/src/order_matching/trade.py b/src/order_matching/trade.py index b19ed1b..0527de3 100644 --- a/src/order_matching/trade.py +++ b/src/order_matching/trade.py @@ -1,6 +1,5 @@ from dataclasses import dataclass - -import pandas as pd +from datetime import datetime from order_matching.execution import Execution from order_matching.side import Side @@ -17,4 +16,4 @@ class Trade: book_order_id: str execution: Execution trade_id: str - timestamp: pd.Timestamp = None + timestamp: datetime diff --git a/tests/test_executed_trades.py b/tests/test_executed_trades.py index bbc1c05..e33d722 100644 --- a/tests/test_executed_trades.py +++ b/tests/test_executed_trades.py @@ -1,4 +1,5 @@ from copy import deepcopy +from datetime import datetime, timedelta import pandas as pd @@ -10,7 +11,7 @@ class TestExecutedTrades: - timestamp = pd.Timestamp.now() + timestamp = datetime.now() def test_init(self) -> None: executed_trades = ExecutedTrades() @@ -45,7 +46,7 @@ def test_get(self) -> None: assert executed_trades.get(timestamp=self.timestamp) == [first_trade, second_trade] third_trade = deepcopy(first_trade) - third_trade.timestamp += pd.Timedelta(1, unit="D") + third_trade.timestamp += timedelta(days=1) executed_trades.add(trades=[third_trade]) assert executed_trades.get(timestamp=self.timestamp) == [first_trade, second_trade] diff --git a/tests/test_matching_engine.py b/tests/test_matching_engine.py index c0980c0..fa9f669 100644 --- a/tests/test_matching_engine.py +++ b/tests/test_matching_engine.py @@ -1,6 +1,6 @@ from copy import deepcopy +from datetime import datetime, timedelta -import pandas as pd from pytest_benchmark.fixture import BenchmarkFixture from order_matching.matching_engine import MatchingEngine @@ -15,7 +15,7 @@ class TestMatchingEngine: def test_matching_with_no_orders(self) -> None: matching_engine = MatchingEngine() - executed_trades = matching_engine.match(timestamp=pd.Timestamp.now()) + executed_trades = matching_engine.match(timestamp=datetime.now()) assert matching_engine.unprocessed_orders.bids == dict() assert matching_engine.unprocessed_orders.offers == dict() @@ -28,8 +28,8 @@ def test_matching_with_complete_order(self) -> None: assert order_book.unprocessed_orders.offers == dict() assert order_book.unprocessed_orders.current_price == float("inf") - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order_first = LimitOrder( side=Side.BUY, price=1.2, size=2.3, timestamp=timestamp, order_id="xyz", trader_id="x" ) @@ -72,8 +72,8 @@ def test_matching_with_complete_order(self) -> None: def test_matching_with_matching_offer_same_size(self) -> None: order_book = MatchingEngine(seed=42) size = 1 - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) sell_order = LimitOrder(side=Side.SELL, price=3, size=size, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([sell_order])), timestamp=transaction_timestamp) @@ -103,8 +103,8 @@ def test_matching_with_matching_offer_same_size(self) -> None: def test_matching_with_matching_bid_same_size(self) -> None: order_book = MatchingEngine(seed=42) size = 1 - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order = LimitOrder(side=Side.BUY, price=4, size=size, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([buy_order])), timestamp=transaction_timestamp) @@ -132,8 +132,8 @@ def test_matching_with_matching_bid_same_size(self) -> None: def test_matching_with_matching_offer_smaller_size(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) sell_order = LimitOrder(side=Side.SELL, price=3, size=2, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([sell_order])), timestamp=transaction_timestamp) @@ -164,8 +164,8 @@ def test_matching_with_matching_offer_smaller_size(self) -> None: def test_matching_with_matching_bid_smaller_size(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order = LimitOrder(side=Side.BUY, price=4, size=2, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([buy_order])), timestamp=transaction_timestamp) @@ -196,8 +196,8 @@ def test_matching_with_matching_bid_smaller_size(self) -> None: def test_matching_with_matching_offer_bigger_size(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) sell_order = LimitOrder(side=Side.SELL, price=3, size=1, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([sell_order])), timestamp=transaction_timestamp) @@ -228,8 +228,8 @@ def test_matching_with_matching_offer_bigger_size(self) -> None: def test_matching_with_matching_offer_bigger_size_and_multiple_bids(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) matching_order = LimitOrder(side=Side.BUY, price=5, size=1, timestamp=timestamp, order_id="c", trader_id="x") buy_orders = [ LimitOrder(side=Side.BUY, price=3, size=2, timestamp=timestamp, order_id="a", trader_id="x"), @@ -272,8 +272,8 @@ def test_matching_with_matching_offer_bigger_size_and_multiple_bids(self) -> Non def test_matching_with_matching_bid_bigger_size_and_multiple_offers(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) matching_order = LimitOrder(side=Side.SELL, price=6, size=1, timestamp=timestamp, order_id="c", trader_id="x") sell_orders = [ LimitOrder(side=Side.SELL, price=7, size=2, timestamp=timestamp, order_id="a", trader_id="x"), @@ -316,8 +316,8 @@ def test_matching_with_matching_bid_bigger_size_and_multiple_offers(self) -> Non def test_matching_with_matching_bid_bigger_size(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order = LimitOrder(side=Side.BUY, price=4, size=1, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([buy_order])), timestamp=transaction_timestamp) @@ -348,8 +348,8 @@ def test_matching_with_matching_bid_bigger_size(self) -> None: def test_matching_with_multiple_matching_offers_bigger_size(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) sell_order_first = LimitOrder( side=Side.SELL, price=3, size=1, timestamp=timestamp, order_id="abc", trader_id="x" ) @@ -406,8 +406,8 @@ def test_matching_with_multiple_matching_offers_bigger_size(self) -> None: def test_matching_with_multiple_matching_bids_bigger_size(self) -> None: order_book = MatchingEngine(seed=66) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order_first = LimitOrder(side=Side.BUY, price=4, size=1, timestamp=timestamp, order_id="abc", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([buy_order_first])), timestamp=transaction_timestamp) @@ -462,8 +462,8 @@ def test_matching_with_multiple_matching_bids_bigger_size(self) -> None: def test_matching_does_not_leave_zero_size_orders_behind(self) -> None: order_book = MatchingEngine(seed=66) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order_first = LimitOrder(side=Side.BUY, price=4, size=1, timestamp=timestamp, order_id="a", trader_id="x") buy_order_second = LimitOrder(side=Side.BUY, price=4, size=1, timestamp=timestamp, order_id="b", trader_id="x") executed_trades = order_book.match( @@ -512,15 +512,15 @@ def test_matching_does_not_leave_zero_size_orders_behind(self) -> None: def test_matching_time_preference(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp(2022, 1, 5) - timedelta = pd.Timedelta(1, unit="D") - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime(2022, 1, 5) + time_delta = timedelta(days=1) + transaction_timestamp = timestamp + timedelta(days=1) buy_order_first = LimitOrder(side=Side.BUY, price=4, size=1, timestamp=timestamp, order_id="abc", trader_id="x") buy_order_second = LimitOrder( - side=Side.BUY, price=4, size=1, timestamp=timestamp - timedelta, order_id="qwe", trader_id="x" + side=Side.BUY, price=4, size=1, timestamp=timestamp - time_delta, order_id="qwe", trader_id="x" ) sell_order = LimitOrder( - side=Side.SELL, price=4, size=0.5, timestamp=timestamp + timedelta, order_id="xyz", trader_id="x" + side=Side.SELL, price=4, size=0.5, timestamp=timestamp + time_delta, order_id="xyz", trader_id="x" ) executed_trades = order_book.match( orders=deepcopy(Orders([sell_order, buy_order_first, buy_order_second])), timestamp=transaction_timestamp @@ -553,8 +553,8 @@ def test_matching_with_market_orders_only(self) -> None: assert order_book.unprocessed_orders.offers == dict() assert order_book.unprocessed_orders.current_price == float("inf") - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order_first = MarketOrder(side=Side.BUY, size=2.3, timestamp=timestamp, order_id="xyz", trader_id="x") executed_trades = order_book.match(orders=deepcopy(Orders([buy_order_first])), timestamp=transaction_timestamp) @@ -587,8 +587,8 @@ def test_matching_with_market_orders_only(self) -> None: def test_matching_with_sell_market_order_after_limit_orders(self) -> None: order_book = MatchingEngine(seed=42) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_orders = [ LimitOrder(side=Side.BUY, price=5.6, size=2.3, timestamp=timestamp, order_id="xyz", trader_id="x"), LimitOrder(side=Side.BUY, price=6.5, size=3.2, timestamp=timestamp, order_id="qwe", trader_id="x"), @@ -632,8 +632,8 @@ def test_matching_with_sell_market_order_after_limit_orders(self) -> None: def test_matching_with_buy_market_orders_after_limit_orders(self) -> None: order_book = MatchingEngine(seed=2) - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) sell_orders = [ LimitOrder(side=Side.SELL, price=5.6, size=2.3, timestamp=timestamp, order_id="xyz", trader_id="x"), LimitOrder(side=Side.SELL, price=6.5, size=3.2, timestamp=timestamp, order_id="qwe", trader_id="x"), @@ -677,8 +677,8 @@ def test_matching_with_buy_market_orders_after_limit_orders(self) -> None: def test_matching_with_order_cancellation(self) -> None: order_book = MatchingEngine() - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order = LimitOrder(side=Side.BUY, price=1.2, size=2.3, timestamp=timestamp, order_id="xyz", trader_id="x") order_book.match(orders=deepcopy(Orders([buy_order])), timestamp=transaction_timestamp) @@ -693,8 +693,8 @@ def test_matching_with_order_cancellation(self) -> None: def test_matching_with_order_cancellation_after_trading(self) -> None: order_book = MatchingEngine() - timestamp = pd.Timestamp.now() - transaction_timestamp = timestamp + pd.Timedelta(1, unit="D") + timestamp = datetime.now() + transaction_timestamp = timestamp + timedelta(days=1) buy_order = LimitOrder(side=Side.BUY, price=1.2, size=3.0, timestamp=timestamp, order_id="xyz", trader_id="x") sell_order = MarketOrder(side=Side.SELL, size=2.0, timestamp=timestamp, order_id="abc", trader_id="y") order_book.match(orders=deepcopy(Orders([buy_order, sell_order])), timestamp=transaction_timestamp) @@ -717,9 +717,9 @@ def test_matching_with_order_cancellation_after_trading(self) -> None: def test_cancellation_of_expired_orders(self) -> None: matching_engine = MatchingEngine() - timestamp = pd.Timestamp.now() - timedelta = pd.Timedelta(1, unit="D") - expiration = timestamp + timedelta + timestamp = datetime.now() + time_delta = timedelta(days=1) + expiration = timestamp + time_delta order = LimitOrder( side=Side.BUY, price=1.2, @@ -734,7 +734,7 @@ def test_cancellation_of_expired_orders(self) -> None: assert matching_engine.unprocessed_orders.bids == {order.price: Orders([order])} assert matching_engine.unprocessed_orders.offers == dict() - matching_engine.match(timestamp=timestamp + timedelta / 2) + matching_engine.match(timestamp=timestamp + time_delta / 2) assert matching_engine.unprocessed_orders.bids == {order.price: Orders([order])} assert matching_engine.unprocessed_orders.offers == dict() diff --git a/tests/test_order.py b/tests/test_order.py index 9fe812d..d3b895f 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -1,3 +1,5 @@ +from datetime import datetime + import pandas as pd import pytest @@ -23,8 +25,8 @@ def test_order_required_defaults( side: Side, price: float, size: float, - timestamp: pd.Timestamp, - expiration: pd.Timestamp, + timestamp: datetime, + expiration: datetime, order_id: str, trader_id: str, execution: Execution, @@ -68,7 +70,7 @@ def test_order_required_defaults( side: Side, price: float, size: float, - timestamp: pd.Timestamp, + timestamp: datetime, order_id: str, trader_id: str, price_number_of_digits: int, @@ -100,7 +102,7 @@ class TestMarketOrder: @pytest.mark.parametrize("order_id", ["a", "b"]) @pytest.mark.parametrize("trader_id", ["x", "y"]) def test_order_required_defaults( - self, side: Side, size: float, timestamp: pd.Timestamp, order_id: str, trader_id: str + self, side: Side, size: float, timestamp: datetime, order_id: str, trader_id: str ) -> None: order = MarketOrder(side=side, size=size, timestamp=timestamp, order_id=order_id, trader_id=trader_id) assert order.side == side diff --git a/tests/test_order_book.py b/tests/test_order_book.py index 6ab1be4..25d1cce 100644 --- a/tests/test_order_book.py +++ b/tests/test_order_book.py @@ -1,4 +1,4 @@ -import pandas as pd +from datetime import datetime, timedelta from order_matching.order import LimitOrder from order_matching.order_book import OrderBook @@ -8,7 +8,7 @@ class TestOrderBook: - timestamp = pd.Timestamp.now() + timestamp = datetime.now() def test_init(self) -> None: order_book = OrderBook() @@ -90,8 +90,8 @@ def test_append_remove_and_get_subset(self) -> None: first_buy_order = self._get_sample_orders().orders[0] second_buy_order = self._get_sample_orders().orders[2] third_buy_order = self._get_sample_orders().orders[4] - timedelta = pd.Timedelta(1, unit="D") - third_buy_order.expiration = self.timestamp + timedelta + time_delta = timedelta(days=1) + third_buy_order.expiration = self.timestamp + time_delta assert first_buy_order.price == second_buy_order.price assert first_buy_order.price != third_buy_order.price @@ -115,7 +115,7 @@ def test_append_remove_and_get_subset(self) -> None: third_buy_order.price: Orders([third_buy_order]), } assert order_book.get_subset(expiration=self.timestamp) == Orders([first_buy_order, second_buy_order]) - assert order_book.get_subset(expiration=self.timestamp + timedelta) == Orders([third_buy_order]) + assert order_book.get_subset(expiration=self.timestamp + time_delta) == Orders([third_buy_order]) order_book.remove(incoming_order=first_buy_order) @@ -124,13 +124,13 @@ def test_append_remove_and_get_subset(self) -> None: third_buy_order.price: Orders([third_buy_order]), } assert order_book.get_subset(expiration=self.timestamp) == Orders([second_buy_order]) - assert order_book.get_subset(expiration=self.timestamp + timedelta) == Orders([third_buy_order]) + assert order_book.get_subset(expiration=self.timestamp + time_delta) == Orders([third_buy_order]) order_book.remove(incoming_order=second_buy_order) assert order_book.bids == {third_buy_order.price: Orders([third_buy_order])} assert order_book.get_subset(expiration=self.timestamp) == Orders() - assert order_book.get_subset(expiration=self.timestamp + timedelta) == Orders([third_buy_order]) + assert order_book.get_subset(expiration=self.timestamp + time_delta) == Orders([third_buy_order]) order_book.remove(incoming_order=third_buy_order) diff --git a/tests/test_orders.py b/tests/test_orders.py index f81cfae..dfaa662 100644 --- a/tests/test_orders.py +++ b/tests/test_orders.py @@ -1,6 +1,6 @@ from copy import deepcopy +from datetime import datetime, timedelta -import pandas as pd import pytest from order_matching.order import LimitOrder, Order @@ -94,14 +94,14 @@ def test_dunder_add_and_len(self) -> None: @staticmethod def _get_test_orders() -> list[Order]: - timestamp = pd.Timestamp.now() + timestamp = datetime.now() return [ LimitOrder(side=Side.SELL, price=4.0, size=10.0, timestamp=timestamp, order_id="a", trader_id="x"), LimitOrder( side=Side.BUY, price=4.0, size=12.0, - timestamp=timestamp - pd.Timedelta(1, unit="D"), + timestamp=timestamp - timedelta(days=1), order_id="b", trader_id="x", ), diff --git a/tests/test_trade.py b/tests/test_trade.py index e3a986d..9999a5e 100644 --- a/tests/test_trade.py +++ b/tests/test_trade.py @@ -1,4 +1,5 @@ from dataclasses import asdict +from datetime import datetime import pandas as pd import pytest @@ -23,7 +24,7 @@ def test_trade_required_defaults( side: Side, price: float, size: float, - timestamp: pd.Timestamp, + timestamp: datetime, incoming_order_id: str, book_order_id: str, trade_id: str,