Repository: liampauling/flumine
Pull request #322 (2020-11-11 08:28:49)

rounding added to size_remaining calculation
history and version updated


Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index a656a5f..12c5b6a 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,6 +3,18 @@
 Release History
 ---------------
 
+1.14.5 (2020-11-11)
++++++++++++++++++++
+
+**Improvements**
+
+- Docs cleanup
+
+**Bug Fixes**
+
+- #318 process customer order ref
+- Rounding on order properties
+
 1.14.4 (2020-11-05)
 +++++++++++++++++++
 
diff --git a/README.md b/README.md
index 410997a..f92eb23 100644
--- a/README.md
+++ b/README.md
@@ -114,7 +114,6 @@ framework.run()
 - Order execution
 - Paper trading
 - Back testing
-- Analytics (in development)
 - Middleware and background workers to enable Scores / RaceCard / InPlayService
 
 ## Dependencies
diff --git a/docs/advanced.md b/docs/advanced.md
index 1ccbe05..b412869 100644
--- a/docs/advanced.md
+++ b/docs/advanced.md
@@ -98,7 +98,7 @@ Before placing an order flumine will check the client and trading controls, this
 
 ### Client Controls
 
-- `MaxOrderCount`: Checks order count is not over betfair transaction limit (1000) 
+- `MaxOrderCount`: Checks order count is not over betfair transaction limit (5000 per hour) 
 
 ### Trading Controls
 
diff --git a/docs/design.md b/docs/design.md
index 28604e4..3dbbbcd 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -21,7 +21,6 @@ ___
 - `CLOSE_MARKET` flumine Close Market update
 - *`STRATEGY_RESET` flumine Strategy Reset update*
 - *`CUSTOM_EVENT` flumine Custom event update*
-- *`NEW_DAY` flumine New Day update*
 - `TERMINATOR` flumine End instance update
 
 The above events are handled in the [flumine class]()
diff --git a/docs/index.md b/docs/index.md
index eb65693..587e327 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -131,7 +131,6 @@ framework.run()
 - Order execution
 - Paper trading
 - Back testing
-- Analytics (in development)
 - Middleware and background workers to enable Scores / RaceCard / InPlayService
 
 ## Dependencies
diff --git a/docs/markets.md b/docs/markets.md
index c540263..cd75221 100644
--- a/docs/markets.md
+++ b/docs/markets.md
@@ -35,4 +35,4 @@ It is common that you want to carry about analysis on a market before passing th
 For example backtesting uses [simulated middleware](https://github.com/liampauling/flumine/blob/master/flumine/markets/middleware.py#L15) in order to calculate order matching.
 
 !!! note
-    Middleware will be executed in the order it is added.
+    Middleware will be executed in the order it is added and before the strategies are processed.
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 7a2cd55..9498bef 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -18,7 +18,7 @@ framework = Flumine(client=client)
 ```
 
 !!! note
-    flumine will handle login, logout and keep alive whilst the framework is running.
+    flumine will handle login, logout and keep alive whilst the framework is running using the `keep_alive` worker.
 
 A strategy can now be created by using the BaseStrategy class:
 
@@ -153,3 +153,14 @@ The extra kwargs above will limit processing to preplay in the final 10 minutes.
 
 !!! tip
     Multiple strategies and markets can be passed, flumine will pass the MarketBooks to the correct strategy via its subscription.
+
+Backtesting uses the `SimulatedExecution` execution class and tries to accurately simulate matching with the following:
+
+- Place/Cancel/Replace latency delay added
+- BetDelay added based on market
+- Queue positioning based on liquidity available
+
+Limitations:
+
+- Queue cancellations
+- Double counting of liquidity
diff --git a/flumine/__version__.py b/flumine/__version__.py
index 7dd489f..92b98ae 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.4"
+__version__ = "1.14.5"
 __author__ = "Liam Pauling"
 __license__ = "MIT"
diff --git a/flumine/order/order.py b/flumine/order/order.py
index 11e7b6b..9195cd2 100644
--- a/flumine/order/order.py
+++ b/flumine/order/order.py
@@ -392,7 +392,7 @@ class BetfairOrder(BaseOrder):
             return self.current_order.size_remaining or 0.0
         except AttributeError:
             if self.size_matched > 0:  # placeResponse does not include sizeRemaining
-                return self.order_type.size - self.size_matched
+                return round(self.order_type.size - self.size_matched, 2)
             else:
                 return self.order_type.size
 
diff --git a/flumine/order/process.py b/flumine/order/process.py
index 791eacd..37f7bc6 100644
--- a/flumine/order/process.py
+++ b/flumine/order/process.py
@@ -1,9 +1,9 @@
 import logging
 
 from ..markets.markets import Markets
-from ..strategy.strategy import Strategies
-from ..order.trade import Trade
 from ..order.order import BaseOrder, OrderStatus, OrderTypes
+from ..order.trade import Trade
+from ..strategy.strategy import Strategies, STRATEGY_NAME_HASH_LENGTH
 
 logger = logging.getLogger(__name__)
 
@@ -11,13 +11,15 @@ logger = logging.getLogger(__name__)
 Handles trade fillkill / green etc.
 Handles orphan orders by creating empty trade and order data from CurrentOrder object/
 """
+
+
 # todo handle fillkill/green/
 
 
 def process_current_orders(markets: Markets, strategies: Strategies, event):
     for current_orders in event.event:
         for current_order in current_orders.orders:
-            strategy_name_hash, order_id = current_order.customer_order_ref.split("-")
+            order_id = current_order.customer_order_ref[STRATEGY_NAME_HASH_LENGTH + 1 :]
             order = markets.get_order(
                 market_id=current_order.market_id,
                 order_id=order_id,
diff --git a/flumine/strategy/strategy.py b/flumine/strategy/strategy.py
index 2cf4194..9232836 100644
--- a/flumine/strategy/strategy.py
+++ b/flumine/strategy/strategy.py
@@ -1,12 +1,14 @@
 from typing import Type, Iterator
+
 from betfairlightweight import filters
 from betfairlightweight.resources import MarketBook
-
-from ..streams.marketstream import BaseStream, MarketStream
-from ..markets.market import Market
 from .runnercontext import RunnerContext
-from ..utils import create_cheap_hash
 from ..clients import BaseClient
+from ..markets.market import Market
+from ..streams.marketstream import BaseStream, MarketStream
+from ..utils import create_cheap_hash
+
+STRATEGY_NAME_HASH_LENGTH = 13
 
 DEFAULT_MARKET_DATA_FILTER = filters.streaming_market_data_filter(
     fields=[
@@ -195,7 +197,7 @@ class BaseStrategy:
 
     @property
     def name_hash(self) -> str:
-        return create_cheap_hash(self.name, 13)
+        return create_cheap_hash(self.name, STRATEGY_NAME_HASH_LENGTH)
 
     def __str__(self):
         return "{0}".format(self.name)


Test patch:
diff --git a/tests/test_process.py b/tests/test_process.py
new file mode 100644
index 0000000..508a07b
--- /dev/null
+++ b/tests/test_process.py
@@ -0,0 +1,55 @@
+import unittest
+from unittest import mock
+
+from flumine import config
+from flumine.markets.market import Market
+from flumine.markets.markets import Markets
+from flumine.order.order import (
+    BaseOrder,
+    BetfairOrder,
+)
+from flumine.order.process import process_current_orders
+from flumine.strategy.strategy import Strategies
+from flumine.utils import create_cheap_hash
+
+
+class BaseOrderTest(unittest.TestCase):
+    def setUp(self) -> None:
+        mock_client = mock.Mock(paper_trade=False)
+        self.mock_trade = mock.Mock(client=mock_client)
+        self.mock_order_type = mock.Mock()
+        self.order = BaseOrder(self.mock_trade, "BACK", self.mock_order_type, 1)
+        config.simulated = True
+
+    def tearDown(self) -> None:
+        config.simulated = False
+
+    def test_process_current_orders_with_default_sep(self):
+        market_book = mock.Mock()
+        markets = Markets()
+        market = Market(
+            flumine=mock.Mock(), market_id="market_id", market_book=market_book
+        )
+
+        markets.add_market("market_id", market)
+
+        strategies = Strategies()
+
+        cheap_hash = create_cheap_hash("strategy_name", 13)
+
+        trade = mock.Mock(market_id="market_id")
+        trade.strategy.name_hash = cheap_hash
+
+        current_order = mock.Mock(
+            customer_order_ref=f"{cheap_hash}I123", market_id="market_id", bet_id=None
+        )
+
+        betfair_order = BetfairOrder(trade=trade, side="BACK", order_type=mock.Mock())
+        betfair_order.id = "123"
+        market.blotter = {"123": betfair_order}
+
+        event = mock.Mock(event=[mock.Mock(orders=[current_order])])
+
+        process_current_orders(markets=markets, strategies=strategies, event=event)
+
+        self.assertEqual(current_order, betfair_order.responses.current_order)