Repository: liampauling/flumine
Pull request #226 (2020-06-29 11:50:57)

Task/224 multi market processing


Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index 0c1f06c..2ecbc7a 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -11,6 +11,7 @@ Release History
 - Custom historical listener/stream added
 - Large order count (per market) optimisations
 - #203 client transaction count
+- #224 multi market processing
 
 **Bug Fixes**
 
diff --git a/flumine/baseflumine.py b/flumine/baseflumine.py
index 6a03d42..1e573da 100644
--- a/flumine/baseflumine.py
+++ b/flumine/baseflumine.py
@@ -128,11 +128,12 @@ class BaseFlumine:
                         strategy.process_market_book, market, market_book
                     )
 
-            self._process_market_orders(market)
+            self._process_market_orders()
 
-    def _process_market_orders(self, market: Market) -> None:
-        for order_package in market.blotter.process_orders(self.client):
-            self.handler_queue.put(order_package)
+    def _process_market_orders(self) -> None:
+        for market in self.markets:
+            for order_package in market.blotter.process_orders(self.client):
+                self.handler_queue.put(order_package)
 
     def _process_order_package(self, order_package) -> None:
         """Validate trading controls and
@@ -182,7 +183,7 @@ class BaseFlumine:
                 for strategy in self.strategies:
                     strategy_orders = market.blotter.strategy_orders(strategy)
                     strategy.process_orders(market, strategy_orders)
-            self._process_market_orders(market)
+        self._process_market_orders()
 
     def _process_custom_event(self, event: events.CustomEvent) -> None:
         try:
@@ -193,8 +194,7 @@ class BaseFlumine:
                     e, event.callback
                 )
             )
-        for market in self.markets:
-            self._process_market_orders(market)
+        self._process_market_orders()
 
     def _process_close_market(self, event: events.CloseMarketEvent) -> None:
         market_id = event.event.market_id
diff --git a/flumine/markets/market.py b/flumine/markets/market.py
index 90af463..e72743b 100644
--- a/flumine/markets/market.py
+++ b/flumine/markets/market.py
@@ -1,6 +1,7 @@
 import datetime
 import logging
 from typing import Optional
+from collections import defaultdict
 from betfairlightweight.resources.bettingresources import MarketBook, MarketCatalogue
 
 from .blotter import Blotter
@@ -61,6 +62,14 @@ class Market:
         order.replace(new_price)
         self.blotter.pending_replace.append(order)
 
+    @property
+    def event(self) -> dict:
+        event = defaultdict(list)
+        for market in self.flumine.markets:
+            if market.event_id == self.event_id:
+                event[market.market_type].append(market)
+        return event
+
     @property
     def event_type_id(self) -> str:
         if self.market_book:
@@ -71,6 +80,11 @@ class Market:
         if self.market_book:
             return self.market_book.market_definition.event_id
 
+    @property
+    def market_type(self) -> str:
+        if self.market_book:
+            return self.market_book.market_definition.market_type
+
     @property
     def seconds_to_start(self):
         return (self.market_start_datetime - datetime.datetime.utcnow()).total_seconds()


Test patch:
diff --git a/flumine/backtest/backtest.py b/flumine/backtest/backtest.py
index afe25d9..032696d 100644
--- a/flumine/backtest/backtest.py
+++ b/flumine/backtest/backtest.py
@@ -7,7 +7,6 @@ from .. import config, utils
 from ..clients import ExchangeType
 from ..exceptions import RunError
 from .utils import PendingPackages
-from ..markets.market import Market
 from ..order.orderpackage import OrderPackageType
 from ..order import process
 from ..markets.middleware import SimulatedMiddleware
@@ -102,11 +101,12 @@ class FlumineBacktest(BaseFlumine):
                 strategy_orders = blotter.strategy_orders(strategy)
                 strategy.process_orders(market, strategy_orders)
 
-            self._process_market_orders(market)
+            self._process_market_orders()
 
-    def _process_market_orders(self, market: Market) -> None:
-        for order_package in market.blotter.process_orders(self.client):
-            self._pending_packages.append(order_package)
+    def _process_market_orders(self) -> None:
+        for market in self.markets:
+            for order_package in market.blotter.process_orders(self.client):
+                self._pending_packages.append(order_package)
 
     def _process_order_package(self, order_package) -> None:
         """Validate trading controls and
diff --git a/tests/test_baseflumine.py b/tests/test_baseflumine.py
index 84b1c7c..b06be67 100644
--- a/tests/test_baseflumine.py
+++ b/tests/test_baseflumine.py
@@ -81,7 +81,8 @@ class BaseFlumineTest(unittest.TestCase):
     def test__process_market_orders(self):
         mock_market = mock.Mock()
         mock_market.blotter.process_orders.return_value = [1, 2, 3]
-        self.base_flumine._process_market_orders(mock_market)
+        self.base_flumine.markets = [mock_market]
+        self.base_flumine._process_market_orders()
         mock_market.blotter.process_orders.assert_called_with(self.mock_client)
 
     def test__process_order_package(self):
@@ -168,7 +169,7 @@ class BaseFlumineTest(unittest.TestCase):
         mock_event = mock.Mock()
         self.base_flumine._process_custom_event(mock_event)
         mock_event.callback.assert_called_with(self.base_flumine, mock_event)
-        mock__process_market_orders.assert_called_with(mock_market)
+        mock__process_market_orders.assert_called_with()
 
     @mock.patch("flumine.baseflumine.BaseFlumine.info")
     @mock.patch("flumine.baseflumine.BaseFlumine.log_control")
diff --git a/tests/test_fluminebacktest.py b/tests/test_fluminebacktest.py
index f0edefa..e5b24af 100644
--- a/tests/test_fluminebacktest.py
+++ b/tests/test_fluminebacktest.py
@@ -66,7 +66,9 @@ class FlumineBacktestTest(unittest.TestCase):
         mock_order_package = mock.Mock()
         mock_market = mock.Mock()
         mock_market.blotter.process_orders.return_value = [mock_order_package]
-        self.flumine._process_market_orders(mock_market)
+        self.flumine.markets = [mock_market]
+        self.flumine._process_market_orders()
+        mock_market.blotter.process_orders.assert_called_with(self.flumine.client)
         self.assertEqual(self.flumine._pending_packages, [mock_order_package])
 
     @mock.patch("flumine.backtest.backtest.BaseFlumine._process_order_package")
diff --git a/tests/test_markets.py b/tests/test_markets.py
index 33ebc8d..a17022f 100644
--- a/tests/test_markets.py
+++ b/tests/test_markets.py
@@ -181,6 +181,21 @@ class MarketTest(unittest.TestCase):
         mock_order.replace.assert_called_with(1.01)
         self.assertEqual(mock_blotter.pending_replace, [mock_order])
 
+    def test_event(self):
+        mock_market_book = mock.Mock()
+        mock_market_book.market_definition = mock.Mock(event_id=12)
+        self.market.market_book = mock_market_book
+
+        self.market.flumine.markets = []
+        self.assertEqual(self.market.event, {})
+
+        m_one = mock.Mock(market_type=1, event_id=12)
+        m_two = mock.Mock(market_type=2, event_id=12)
+        m_three = mock.Mock(market_type=3, event_id=123)
+        m_four = mock.Mock(market_type=1, event_id=12)
+        self.market.flumine.markets = [m_one, m_two, m_three, m_four]
+        self.assertEqual(self.market.event, {1: [m_one, m_four], 2: [m_two]})
+
     def test_event_type_id(self):
         mock_market_book = mock.Mock()
         self.market.market_book = mock_market_book
@@ -195,6 +210,13 @@ class MarketTest(unittest.TestCase):
             self.market.event_id, mock_market_book.market_definition.event_id
         )
 
+    def test_market_type(self):
+        mock_market_book = mock.Mock()
+        self.market.market_book = mock_market_book
+        self.assertEqual(
+            self.market.market_type, mock_market_book.market_definition.market_type
+        )
+
     def test_seconds_to_start(self):
         mock_market_catalogue = mock.Mock()
         mock_market_catalogue.market_start_time = datetime.datetime.utcfromtimestamp(1)