Repository: liampauling/flumine
Pull request #305 (2020-10-30 08:26:17)

size_reduction handling added to simulated execution on cancel


Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index 5a46bc2..e985ddb 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,21 +3,6 @@
 Release History
 ---------------
 
-1.14.2 (2020-11-02)
-+++++++++++++++++++
-
-**Improvements**
-
--
-
-**Bug Fixes**
-
--
-
-**Libraries**
-
-- betfairlightweight upgraded to 2.10.0
-
 1.14.1 (2020-10-29)
 +++++++++++++++++++
 
diff --git a/flumine/__version__.py b/flumine/__version__.py
index 9299449..d8848ae 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.14.2"
+__version__ = "1.14.1"
 __author__ = "Liam Pauling"
 __license__ = "MIT"
diff --git a/flumine/execution/simulatedexecution.py b/flumine/execution/simulatedexecution.py
index 8fe3bd6..221aaff 100644
--- a/flumine/execution/simulatedexecution.py
+++ b/flumine/execution/simulatedexecution.py
@@ -65,7 +65,10 @@ class SimulatedExecution(BaseExecution):
                     order, simulated_response, order_package.package_type
                 )
                 if simulated_response.status == "SUCCESS":
-                    order.execution_complete()
+                    if order.size_cancelled == order.size_remaining:
+                        order.execution_complete()
+                    else:
+                        order.executable()
                 elif simulated_response.status == "FAILURE":
                     order.executable()
 
diff --git a/requirements.txt b/requirements.txt
index 2eae7bb..9a938fb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-betfairlightweight==2.10.0
+betfairlightweight==2.9.2
 tenacity==5.0.3
 python-json-logger==2.0.1
 requests


Test patch:
diff --git a/flumine/backtest/simulated.py b/flumine/backtest/simulated.py
index dfdf2ed..eff8941 100644
--- a/flumine/backtest/simulated.py
+++ b/flumine/backtest/simulated.py
@@ -132,7 +132,10 @@ class Simulated:
     def cancel(self) -> SimulatedCancelResponse:
         # simulates cancelOrder request->cancel->response
         if self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT:
-            self.size_cancelled = self.size_remaining
+            _size_reduction = (
+                self.order.update_data.get("size_reduction") or self.size_remaining
+            )  # todo handle when size_reduction provided greater than size_remaining?
+            self.size_cancelled = _size_reduction
             return SimulatedCancelResponse(
                 status="SUCCESS",  # todo handle errors
                 size_cancelled=self.size_cancelled,
diff --git a/tests/test_execution.py b/tests/test_execution.py
index 214a712..c79213c 100644
--- a/tests/test_execution.py
+++ b/tests/test_execution.py
@@ -886,7 +886,7 @@ class SimulatedExecutionTest(unittest.TestCase):
 
     @mock.patch("flumine.execution.simulatedexecution.SimulatedExecution._order_logger")
     def test_execute_cancel(self, mock__order_logger):
-        mock_order = mock.Mock()
+        mock_order = mock.Mock(size_cancelled=2, size_remaining=2)
         mock_order.trade.__enter__ = mock.Mock()
         mock_order.trade.__exit__ = mock.Mock()
         mock_order_package = mock.Mock()
@@ -904,6 +904,26 @@ class SimulatedExecutionTest(unittest.TestCase):
         mock_order.trade.__enter__.assert_called_with()
         mock_order.trade.__exit__.assert_called_with(None, None, None)
 
+    @mock.patch("flumine.execution.simulatedexecution.SimulatedExecution._order_logger")
+    def test_execute_cancel_executable(self, mock__order_logger):
+        mock_order = mock.Mock(size_cancelled=2, size_remaining=3)
+        mock_order.trade.__enter__ = mock.Mock()
+        mock_order.trade.__exit__ = mock.Mock()
+        mock_order_package = mock.Mock()
+        mock_order_package.client.paper_trade = False
+        mock_order_package.__iter__ = mock.Mock(return_value=iter([mock_order]))
+        mock_sim_resp = mock.Mock()
+        mock_sim_resp.status = "SUCCESS"
+        mock_order.simulated.cancel.return_value = mock_sim_resp
+        self.execution.execute_cancel(mock_order_package, None)
+        mock_order.simulated.cancel.assert_called_with()
+        mock__order_logger.assert_called_with(
+            mock_order, mock_sim_resp, mock_order_package.package_type
+        )
+        mock_order.executable.assert_called_with()
+        mock_order.trade.__enter__.assert_called_with()
+        mock_order.trade.__exit__.assert_called_with(None, None, None)
+
     @mock.patch("flumine.execution.simulatedexecution.SimulatedExecution._order_logger")
     def test_execute_cancel_failure(self, mock__order_logger):
         mock_order = mock.Mock()
diff --git a/tests/test_simulated.py b/tests/test_simulated.py
index 47f064a..20d7d47 100644
--- a/tests/test_simulated.py
+++ b/tests/test_simulated.py
@@ -208,11 +208,19 @@ class SimulatedTest(unittest.TestCase):
         self.assertEqual(resp.error_code, "dubs of the mad skint and british")
 
     def test_cancel(self):
+        self.simulated.order.update_data = {}
         resp = self.simulated.cancel()
         self.assertEqual(self.simulated.size_cancelled, 2.0)
         self.assertEqual(resp.status, "SUCCESS")
         self.assertEqual(resp.size_cancelled, 2.0)
 
+    def test_cancel_reduction(self):
+        self.simulated.order.update_data = {"size_reduction": 0.50}
+        resp = self.simulated.cancel()
+        self.assertEqual(self.simulated.size_cancelled, 0.50)
+        self.assertEqual(resp.status, "SUCCESS")
+        self.assertEqual(resp.size_cancelled, 0.50)
+
     def test_cancel_else(self):
         self.simulated.order.order_type.ORDER_TYPE = OrderTypes.MARKET_ON_CLOSE
         resp = self.simulated.cancel()