QuantRocket

Current positions ignored in intraday strategy?


#1

Hi there!

I tried to run a simple intraday strategy through paper trading. A simple long-only strategy that runs every 1 minute and trades much less often and only one security. It ran as expected on backtesting, however, live trading on paper account failed. The strategy issued orders every minute ignoring current positions already held. I.e. if I have a chain of subsequent 1’s in signals dataframe, for every single one of them strategy issues a buy order, blotter executes it, then next minute signal is still 1, strategy issues another equally sized order ignoring current position already held, and so on until entire account assets are depleted. I checked logs and orders were definitely filled before the next run of the strategy (however it would be nice to know what would happen if they were not).
Funnily, I also attached closing MOC dependant order to each order (as per documentation). Just as an experiment as I didn’t know if offset MOC orders get canceled automatically by broker/exchange and I wanted a way to make sure strategy closes all its positions before market close. Well, at the end of the day strategy ended up with a huge negative position in the traded security (despite strategy was long-only) which blotter recognized as ‘uncategorized’ (I suppose MOC orders don’t return Order-ref on execution?).
My question is how can I troubleshoot this situation as I cannot really attach a debugger to moonshot (SSH again) and logs are a mess with hundreds of orders (most canceled) and thousands of executions? All that I can find in documentation on troubleshooting seem to rely to backtesting and not live trading.
Thank you!


#2

Just checked again manually - yep, it places the order every time I run the strategy even though ‘quantrocket blotter positions’ correctly reflects position in the traded security and OrderRef with strategy name. The position keeps growing infinitely.

One more question: how can I reset blotter to is actually held on broker side? I went to TWS to close positions manually (even though it is paper account) while IB client was disconnected. Now blotter keeps displaying this enormous negative position even though it is already closed. ‘blotter --broker --diff’ display the difference correctly, but there seem to be no way to tell blotter to forget this erroneous position?
Thanks again!


#3

Moonshot looks at positions and open orders as explained here and it assumes all open orders will be filled. So if you have resting MOC orders which will zero out your open position but Moonshot has a long signal, Moonshot will send a new order to achieve your target weight.

If you are attaching child orders you should not run Moonshot again until they fill, to avoid this. Or you can skip the child orders and use quantrocket blotter close to be flat by the end of the day.

To correct for manually closing positions in TWS, you will need to manually edit the LatestPosition table in quantrocket.blotter.executions.sqlite. Simply delete the rows for the manually closed positions.


#4

Thank you Brian! That explains it!

I thought using MOC to ensure all positions are closed by day end should be more reliable, as during high volatility trading can end suddenly.

I will probably just modify strategy to stop trading if there are any uncompleted orders. I will also build some ‘panic’ function that will stop trading and go cash immediately if, for instance, strategy actual absolute position differs significantly from its allocation.
Thanks again!


#5

Another question:

‘quantrocket blotter pnl’ returns error (I swear I didn’t touch quantrocket.blotter.pnl.sqlite, however my quantrocket installation is quite old and I upgraded it some time ago following documentation):

2020-03-27 20:08:26 quantrocket.blotter: ERROR Traceback (most recent call last):
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_wsgi_py”, line 30, in app
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1994, in call
2020-03-27 20:08:26 quantrocket.blotter: ERROR return self.wsgi_app(environ, start_response)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1985, in wsgi_app
2020-03-27 20:08:26 quantrocket.blotter: ERROR response = self.handle_exception(e)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask_restful/init.py”, line 271, in error_router
2020-03-27 20:08:26 quantrocket.blotter: ERROR return original_handler(e)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1540, in handle_exception
2020-03-27 20:08:26 quantrocket.blotter: ERROR reraise(exc_type, exc_value, tb)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/_compat.py”, line 32, in reraise
2020-03-27 20:08:26 quantrocket.blotter: ERROR raise value.with_traceback(tb)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1982, in wsgi_app
2020-03-27 20:08:26 quantrocket.blotter: ERROR response = self.full_dispatch_request()
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1614, in full_dispatch_request
2020-03-27 20:08:26 quantrocket.blotter: ERROR rv = self.handle_user_exception(e)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask_restful/init.py”, line 271, in error_router
2020-03-27 20:08:26 quantrocket.blotter: ERROR return original_handler(e)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1517, in handle_user_exception
2020-03-27 20:08:26 quantrocket.blotter: ERROR reraise(exc_type, exc_value, tb)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/_compat.py”, line 32, in reraise
2020-03-27 20:08:26 quantrocket.blotter: ERROR raise value.with_traceback(tb)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1612, in full_dispatch_request
2020-03-27 20:08:26 quantrocket.blotter: ERROR rv = self.dispatch_request()
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/app.py”, line 1598, in dispatch_request
2020-03-27 20:08:26 quantrocket.blotter: ERROR return self.view_functionsrule.endpoint
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask_restful/init.py”, line 477, in wrapper
2020-03-27 20:08:26 quantrocket.blotter: ERROR resp = resource(*args, **kwargs)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask/views.py”, line 84, in view
2020-03-27 20:08:26 quantrocket.blotter: ERROR return self.dispatch_request(*args, **kwargs)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/flask_restful/init.py”, line 587, in dispatch_request
2020-03-27 20:08:26 quantrocket.blotter: ERROR resp = meth(*args, **kwargs)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/site-packages/webargs/core.py”, line 441, in wrapper
2020-03-27 20:08:26 quantrocket.blotter: ERROR return func(*args, **kwargs)
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_app_py”, line 634, in get
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_blotter_pnl_py”, line 264, in wrapper
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_blotter_pnl_py”, line 332, in get_pnl
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_blotter_pnl_py”, line 51, in calculate_pnl
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_blotter_pnl_py”, line 191, in _calculate_pnl_for_account_orderref
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “sym://qrocket_sqlite_py”, line 106, in insert_into
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/subprocess.py”, line 336, in check_output
2020-03-27 20:08:26 quantrocket.blotter: ERROR **kwargs).stdout
2020-03-27 20:08:26 quantrocket.blotter: ERROR File “/opt/conda/lib/python3.6/subprocess.py”, line 418, in run
2020-03-27 20:08:26 quantrocket.blotter: ERROR output=stdout, stderr=stderr)
2020-03-27 20:08:26 quantrocket.blotter: ERROR subprocess.CalledProcessError: Command ‘[‘sqlite3’, ‘/var/lib/quantrocket/quantrocket.blotter.pnl.sqlite’]’ returned non-zero exit status 1.
2020-03-27 20:08:26 quantrocket.blotter: ERROR


#6

In the detailed logs there should a be a line right before the traceback which prints the SQL error. Please post the line.

It might be due to an open issue that occurs if you query summary pnl with dates only. If that’s what happening, as a workaround please add an additional parameter such as an account number or order ref, or query detailed pnl.