Repository: liampauling/flumine
Pull request #379 (2021-02-25 11:25:40)

incorrect calculation of potential exposure (missing potential part)


Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index e52500f..2cdc7d3 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,13 +3,6 @@
 Release History
 ---------------
 
-1.17.2 (2021-02-25)
-+++++++++++++++++++
-
-**Improvements**
-
-- Allow patching of stream retry wait arg
-
 1.17.1 (2021-02-24)
 +++++++++++++++++++
 
diff --git a/flumine/__version__.py b/flumine/__version__.py
index 5e572ec..eee2122 100644
--- a/flumine/__version__.py
+++ b/flumine/__version__.py
@@ -1,6 +1,6 @@
 __title__ = "flumine"
 __description__ = "Betfair trading framework"
 __url__ = "https://github.com/liampauling/flumine"
-__version__ = "1.17.2"
+__version__ = "1.17.1"
 __author__ = "Liam Pauling"
 __license__ = "MIT"
diff --git a/flumine/controls/tradingcontrols.py b/flumine/controls/tradingcontrols.py
index 00abb9c..dcbefe9 100644
--- a/flumine/controls/tradingcontrols.py
+++ b/flumine/controls/tradingcontrols.py
@@ -140,12 +140,15 @@ class StrategyExposure(BaseControl):
 
             # per selection
             market = self.flumine.markets.markets[order.market_id]
-            exposure = market.blotter.selection_exposure(strategy, lookup=order.lookup)
-            if exposure > strategy.max_selection_exposure:
+            selection_exposure = market.blotter.selection_exposure(
+                strategy, lookup=order.lookup
+            )
+            potential_exposure = selection_exposure + exposure
+            if potential_exposure > strategy.max_selection_exposure:
                 return self._on_error(
                     order,
-                    "Potential selection exposure ({0}) is greater than strategy.max_selection_exposure ({1})".format(
-                        exposure,
+                    "Potential selection exposure ({0:.2f}) is greater than strategy.max_selection_exposure ({1})".format(
+                        potential_exposure,
                         strategy.max_selection_exposure,
                     ),
                 )
diff --git a/flumine/streams/basestream.py b/flumine/streams/basestream.py
index 7d0b539..b193de1 100644
--- a/flumine/streams/basestream.py
+++ b/flumine/streams/basestream.py
@@ -3,7 +3,6 @@ import queue
 import logging
 import betfairlightweight
 from betfairlightweight import StreamListener
-from tenacity import wait_exponential
 
 logger = logging.getLogger(__name__)
 
@@ -12,7 +11,6 @@ class BaseStream(threading.Thread):
 
     LISTENER = StreamListener
     MAX_LATENCY = 0.5
-    RETRY_WAIT = wait_exponential(multiplier=1, min=2, max=20)
 
     def __init__(
         self,
diff --git a/flumine/streams/datastream.py b/flumine/streams/datastream.py
index 9651ec6..4781d83 100644
--- a/flumine/streams/datastream.py
+++ b/flumine/streams/datastream.py
@@ -1,5 +1,5 @@
 import logging
-from tenacity import retry
+from tenacity import retry, wait_exponential
 from betfairlightweight import StreamListener
 from betfairlightweight import BetfairError
 from betfairlightweight.streaming.stream import BaseStream as BFBaseStream
@@ -10,8 +10,6 @@ from ..exceptions import ListenerError
 
 logger = logging.getLogger(__name__)
 
-RETRY_WAIT = BaseStream.RETRY_WAIT
-
 
 """
 Custom listener that doesn't do any processing,
@@ -100,7 +98,7 @@ class DataStream(BaseStream):
         BaseStream.__init__(self, *args, **kwargs)
         self._listener = self.LISTENER(output_queue=self.flumine.handler_queue)
 
-    @retry(wait=RETRY_WAIT)
+    @retry(wait=wait_exponential(multiplier=1, min=2, max=20))
     def run(self) -> None:
         logger.info(
             "Starting DataStream {0}".format(self.stream_id),
diff --git a/flumine/streams/marketstream.py b/flumine/streams/marketstream.py
index 82834e6..bc3af27 100644
--- a/flumine/streams/marketstream.py
+++ b/flumine/streams/marketstream.py
@@ -1,18 +1,16 @@
 import queue
 import logging
 from betfairlightweight import BetfairError
-from tenacity import retry
+from tenacity import retry, wait_exponential
 
 from .basestream import BaseStream
 from ..events.events import MarketBookEvent
 
 logger = logging.getLogger(__name__)
 
-RETRY_WAIT = BaseStream.RETRY_WAIT
-
 
 class MarketStream(BaseStream):
-    @retry(wait=RETRY_WAIT)
+    @retry(wait=wait_exponential(multiplier=1, min=2, max=20))
     def run(self) -> None:
         logger.info(
             "Starting MarketStream {0}".format(self.stream_id),
diff --git a/flumine/streams/orderstream.py b/flumine/streams/orderstream.py
index d816c17..d7e8f56 100644
--- a/flumine/streams/orderstream.py
+++ b/flumine/streams/orderstream.py
@@ -1,7 +1,7 @@
 import queue
 import logging
 from betfairlightweight import BetfairError, filters
-from tenacity import retry
+from tenacity import retry, wait_exponential
 
 from .basestream import BaseStream
 from ..events.events import CurrentOrdersEvent
@@ -9,11 +9,9 @@ from .. import config
 
 logger = logging.getLogger(__name__)
 
-RETRY_WAIT = BaseStream.RETRY_WAIT
-
 
 class OrderStream(BaseStream):
-    @retry(wait=RETRY_WAIT)
+    @retry(wait=wait_exponential(multiplier=1, min=2, max=20))
     def run(self) -> None:
         logger.info(
             "Starting OrderStream {0}".format(self.stream_id),


Test patch:
diff --git a/tests/test_tradingcontrols.py b/tests/test_tradingcontrols.py
index 9d82705..8ddb182 100644
--- a/tests/test_tradingcontrols.py
+++ b/tests/test_tradingcontrols.py
@@ -381,14 +381,13 @@ class TestStrategyExposure(unittest.TestCase):
         order2.average_price_matched = 0.0
         order2.size_matched = 0
 
-        self.market.blotter["order1"] = order1
         self.market.blotter["order2"] = order2
 
         self.trading_control._validate(order1, OrderPackageType.PLACE)
         self.assertEqual(1, mock_on_error.call_count)
         mock_on_error.assert_called_with(
             order1,
-            "Potential selection exposure (14.0) is greater than strategy.max_selection_exposure (10)",
+            "Potential selection exposure (14.00) is greater than strategy.max_selection_exposure (10)",
         )
 
     @mock.patch("flumine.controls.tradingcontrols.StrategyExposure._on_error")
@@ -428,7 +427,7 @@ class TestStrategyExposure(unittest.TestCase):
         mock_market = mock.Mock()
         mock_market.blotter.selection_exposure.return_value = 12.0
         self.mock_flumine.markets.markets = {"1.234": mock_market}
-        mock_order = mock.Mock(market_id="1.234", lookup=(1, 2, 3))
+        mock_order = mock.Mock(market_id="1.234", lookup=(1, 2, 3), side="LAY")
         mock_order.trade.strategy.max_order_exposure = 10
         mock_order.trade.strategy.max_selection_exposure = 10
         mock_order.order_type.ORDER_TYPE = OrderTypes.LIMIT
@@ -438,5 +437,5 @@ class TestStrategyExposure(unittest.TestCase):
         self.trading_control._validate(mock_order, OrderPackageType.PLACE)
         mock_on_error.assert_called_with(
             mock_order,
-            "Potential selection exposure (12.0) is greater than strategy.max_selection_exposure (10)",
+            "Potential selection exposure (12.12) is greater than strategy.max_selection_exposure (10)",
         )