Repository: liampauling/flumine
Pull request #306 (2020-10-30 08:54:30)

_process_cleared_orders called on market closure when backtesting or …
…paper trading

backtest logging control example added
setup update


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/baseflumine.py b/flumine/baseflumine.py
index 555fe83..ba6d359 100644
--- a/flumine/baseflumine.py
+++ b/flumine/baseflumine.py
@@ -21,7 +21,6 @@ from .controls.tradingcontrols import OrderValidation, StrategyExposure
 from .controls.loggingcontrols import LoggingControl
 from . import config, utils
 
-
 logger = logging.getLogger(__name__)
 
 
@@ -268,7 +267,10 @@ class BaseFlumine:
             if stream_id in strategy.stream_ids:
                 strategy.process_closed_market(market, event.event)
 
-        self.cleared_market_queue.put(market_id)
+        if self.BACKTEST or self.client.paper_trade:
+            self._process_cleared_orders(events.ClearedOrdersEvent(market))
+        else:
+            self.cleared_market_queue.put(market_id)
         self.log_control(event)
         logger.info("Market closed", extra={"market_id": market_id, **self.info})
 
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
diff --git a/setup.py b/setup.py
index fd4dee6..d066f0d 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,13 @@ setup(
     name=about["__title__"],
     version=about["__version__"],
     packages=find_packages(
-        exclude=["examples", "examples.strategies", "examples.workers"]
+        exclude=[
+            "examples",
+            "examples.strategies",
+            "examples.workers",
+            "examples.middleware",
+            "examples.controls",
+        ]
     ),
     package_dir={"flumine": "flumine"},
     install_requires=INSTALL_REQUIRES,


Test patch:
diff --git a/examples/controls/__init__.py b/examples/controls/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/examples/controls/backtestloggingcontrol.py b/examples/controls/backtestloggingcontrol.py
new file mode 100644
index 0000000..a79eae8
--- /dev/null
+++ b/examples/controls/backtestloggingcontrol.py
@@ -0,0 +1,70 @@
+import csv
+import logging
+from flumine.controls.loggingcontrols import LoggingControl
+
+logger = logging.getLogger(__name__)
+
+FIELDNAMES = [
+    "bet_id",
+    "strategy_name",
+    "market_id",
+    "selection_id",
+    "trade_id",
+    "date_time_placed",
+    "price",
+    "price_matched",
+    "size",
+    "size_matched",
+    "profit",
+    "side",
+    "elapsed_seconds_executable",
+    "order_status",
+    "market_note",
+    "notes",
+]
+
+
+class BacktestLoggingControl(LoggingControl):
+    NAME = "BACKTEST_LOGGING_CONTROL"
+
+    def __init__(self, *args, **kwargs):
+        super(BacktestLoggingControl, self).__init__(*args, **kwargs)
+        self._setup()
+
+    def _setup(self):
+        with open("orders.txt", "w") as m:
+            csv_writer = csv.DictWriter(m, delimiter=",", fieldnames=FIELDNAMES)
+            csv_writer.writeheader()
+
+    def _process_cleared_orders_meta(self, event):
+        orders = event.event
+        with open("orders.txt", "a") as m:
+            for order in orders:
+                try:
+                    order_data = {
+                        "bet_id": order.bet_id,
+                        "strategy_name": order.trade.strategy,
+                        "market_id": order.market_id,
+                        "selection_id": order.selection_id,
+                        "trade_id": order.trade.id,
+                        "date_time_placed": order.responses.date_time_placed,
+                        "price": order.order_type.price,
+                        "price_matched": order.average_price_matched,
+                        "size": order.order_type.size,
+                        "size_matched": order.size_matched,
+                        "profit": order.simulated.profit,
+                        "side": order.side,
+                        "elapsed_seconds_executable": order.elapsed_seconds_executable,
+                        "order_status": order.status.value,
+                        "market_note": order.trade.market_notes,
+                        "notes": order.trade.notes_str,
+                    }
+                    csv_writer = csv.DictWriter(m, delimiter=",", fieldnames=FIELDNAMES)
+                    csv_writer.writerow(order_data)
+                except Exception as e:
+                    logger.error(
+                        "_process_cleared_orders_meta: %s" % e,
+                        extra={"order": order, "error": e},
+                    )
+
+        logger.info("Orders updated", extra={"order_count": len(orders)})
diff --git a/tests/test_baseflumine.py b/tests/test_baseflumine.py
index a7004f4..05d98a6 100644
--- a/tests/test_baseflumine.py
+++ b/tests/test_baseflumine.py
@@ -314,9 +314,13 @@ class BaseFlumineTest(unittest.TestCase):
 
         self.assertEqual(len(self.base_flumine.markets._markets), 3)
 
+    @mock.patch("flumine.baseflumine.events")
+    @mock.patch("flumine.baseflumine.BaseFlumine._process_cleared_orders")
     @mock.patch("flumine.baseflumine.BaseFlumine.info")
     @mock.patch("flumine.baseflumine.BaseFlumine.log_control")
-    def test__process_close_market_closed_paper(self, mock_log_control, mock_info):
+    def test__process_close_market_closed_paper(
+        self, mock_log_control, mock_info, mock__process_cleared_orders, mock_events
+    ):
         self.base_flumine.client.paper_trade = True
         mock_strategy = mock.Mock()
         mock_strategy.stream_ids = [1, 2, 3]
@@ -338,6 +342,9 @@ class BaseFlumineTest(unittest.TestCase):
         mock_event.event = mock_market_book
         self.base_flumine._process_close_market(mock_event)
         self.assertEqual(len(self.base_flumine.markets._markets), 4)
+        mock__process_cleared_orders.assert_called_with(
+            mock_events.ClearedOrdersEvent()
+        )
 
     @mock.patch("flumine.baseflumine.events")
     @mock.patch("flumine.baseflumine.BaseFlumine.log_control")