Skip to content

V2: Order Flow and Adapter Design #6

@FergusInLondon

Description

@FergusInLondon

Nothing is set in stone, and obviously this design is liable to change. I doubt the requirements themselves will change though.

Requirements:

  • The API adapter must be able to execute: market_order and limit_order operations for both BUY and SELL types.
  • The API adapter should be able to determine whether an order is by quantity or price.
  • Orders originating from the Strategy must run through an authorisation guard that determines whether a transaction is allowed, and fill any parameters that are missing - i.e. perform risk mitigation.
  • The API adapter must provide appropriate updates on the status of an order, and the resulting status of the account.
  • The SyncAgent must ensure that it maintains the correct state for this information.
  • Metrics/observability should be available for all orders and subsequent updates.

Current Idea

swimlanes-73148393c9f1ff23b20521d7b2998e63

Questions

Is the authorise call really mandatory?

  • For most strategies which simply buy/sell one given asset, perhaps a simple flag could be used to skip the authorise call - i.e. force=False.
  • Alternatively the authorise() call could no longer be an abstract method, and could simply verify that arguments are correct - i.e. if SELL then is there a corresponding position to actually sell?

Potential Gotchas

SyncAgent race conditions

All Orders are triggered via the BaseStrategy - specificaly the SyncAgent strategy - which means they run concurrently to the strategy; this may lead to odd race conditions or duplicate orders. Although the queue.Queue that's used to interact with the SyncAgent should ensure sequential operations, that still doesn't account for state changes between (a) the order being requested in the queue, and (b) the order being placed.

Potential Mitigation: This can't really be solved simply with locking, as order updates will be inbound/pending whilst the message is awaing processing. There must be a clearly defined and logical sequence of (a) checking the registry, (b) updating the registry, (c) calling authorise(...), and (d) making the transaction. The SyncAgent event loop must ensure that a given request has been acknowledged before continuing to process the next message.

Work Required:

  • Registry of all orders in the AccountStatus
  • Appropriate updates to the registry via SyncAgent
  • A clearly defined interface that Adapters are expected to follow for allowing orders.
  • Enabling of Test orders - via a flag that defaults to True - to verify order validity prior to placing the order.
  • Suitable handling of non 2xx error codes in the API adapter
  • A test suite that can be used to verify that API adapters are correctly implemented (i.e. a Gherkin file that can be used for all adapters)
  • Before placing an order there must be protection against conflicting or duplicate orders, including pending ones (See race condition mitigations above).

Inspirations

quantopian/zipline

Zipline has a really simple interface to execute orders - a method named order_asset([symbol], [qty]). This doesn't have the flexibility that the above design has, but it is certainly a requires a simpler - and therefore likely less error-prone - implementation.

quantconnect

QuantConnect supports six types of order, each via their own function. This is likely a far better and cuts down on the params in the TransactionRequest that the strategy needs to supply.

Additionally the API for making orders returns a "Ticket" object, allowing you to retrieve more information - the kind of information that the SyncAgent maintains.

arcadetrader

ArcadeTrader actually has the strategy return an object determining whether a trade should be made; this is simpler, but really conflicts with the SyncAgent idea - and would require a few design changes.

Being able to associate a reason - i.e. a string describing the conditions which triggered the request - with a trade seems nice though.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions