Debugging live strategy#
In this notebook, we show how to debug live trading strategy instance using Python and Jupyter notebook.
Downloading the trades from the live instance
Reading data to
State
objectInspecting
State
in Python
Download live data#
Each strategy Docker instances offers a webhook that allows access the data of this strategy, include
State
object that is the flat file state of the all the strategy current and past decision makingNote that
State
class and any children classes in the state tree may have changes between versions and decoding might need you to use a specific version oftrade-executor
[1]:
from tradeexecutor.monkeypatch.dataclasses_json import patch_dataclasses_json
from tradeexecutor.state.state import State
import requests
# Currently needed because unpatched dataclasses_json package issues
patch_dataclasses_json()
# Public internet endpoint as exposed by the trade executor Docker
webbhook_url = "https://pancake-eth-usd-sma.tradingstrategy.ai"
state_api = f"{webbhook_url}/state"
resp = requests.get(state_api)
state_blob = resp.content
print(f"Downloaded {len(state_blob):,} bytes state data")
state = State.from_json(state_blob)
print(f"trade-executor was launched at: {state.created_at}, we have {len(list(state.portfolio.get_all_trades()))} trades")
Downloaded 6,467 bytes state data
---------------------------------------------------------------------------
JSONDecodeError Traceback (most recent call last)
Cell In[1], line 19
15 state_blob = resp.content
17 print(f"Downloaded {len(state_blob):,} bytes state data")
---> 19 state = State.from_json(state_blob)
21 print(f"trade-executor was launched at: {state.created_at}, we have {len(list(state.portfolio.get_all_trades()))} trades")
File ~/.pyenv/versions/3.10.8/lib/python3.10/site-packages/dataclasses_json/api.py:58, in DataClassJsonMixin.from_json(cls, s, parse_float, parse_int, parse_constant, infer_missing, **kw)
49 @classmethod
50 def from_json(cls: Type[A],
51 s: JsonData,
(...)
56 infer_missing=False,
57 **kw) -> A:
---> 58 kvs = json.loads(s,
59 parse_float=parse_float,
60 parse_int=parse_int,
61 parse_constant=parse_constant,
62 **kw)
63 return cls.from_dict(kvs, infer_missing=infer_missing)
File ~/.pyenv/versions/3.10.8/lib/python3.10/json/__init__.py:346, in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
341 s = s.decode(detect_encoding(s), 'surrogatepass')
343 if (cls is None and object_hook is None and
344 parse_int is None and parse_float is None and
345 parse_constant is None and object_pairs_hook is None and not kw):
--> 346 return _default_decoder.decode(s)
347 if cls is None:
348 cls = JSONDecoder
File ~/.pyenv/versions/3.10.8/lib/python3.10/json/decoder.py:337, in JSONDecoder.decode(self, s, _w)
332 def decode(self, s, _w=WHITESPACE.match):
333 """Return the Python representation of ``s`` (a ``str`` instance
334 containing a JSON document).
335
336 """
--> 337 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
338 end = _w(s, end).end()
339 if end != len(s):
File ~/.pyenv/versions/3.10.8/lib/python3.10/json/decoder.py:355, in JSONDecoder.raw_decode(self, s, idx)
353 obj, end = self.scan_once(s, idx)
354 except StopIteration as err:
--> 355 raise JSONDecodeError("Expecting value", s, err.value) from None
356 return obj, end
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Examining data#
You can check what individual persistent objects are made of.
In this example, we have one blockchain trade whose transactions were broadcasted to the blockchain, but for which we never got transaction receipts back to the blockchain.
[ ]:
# Inspect a single position
position = next(iter(state.portfolio.closed_positions.values()))
print(position)
print("Value: ", position.get_value())
print("Quantity: ", position.get_quantity())
print("Successful trades:")
for t in position.get_successful_trades():
print(f" {t}")
print("Failed trades:")
for t in position.get_failed_trades():
print(f" {t}")
print("Any trades:")
for trade_id, t in position.trades.items():
print(f" {t}")