alpacahq / Alpaca-API

The Alpaca API is a developer interface for trading operations and market data reception through the Alpaca platform.
https://alpaca.markets/
143 stars 13 forks source link

Partial FILL activities are not totally ordered #170

Open spazmodius opened 3 years ago

spazmodius commented 3 years ago

Describe the bug When I fetch FILL activities, partial fills that occur in the same millisecond may be listed out of order, as evident by the cum_qty amount.

To Reproduce GET https://api.alpaca.markets/v2/account/activities/FILL?date=2021-01-27

For my account, this returns

[
    {
      id: '20210127144930176::ddc0a142-ebfd-4890-9021-641d33e58742',
      activity_type: 'FILL',
      transaction_time: '2021-01-27T19:49:30.176Z',
      type: 'partial_fill',
      price: '31.6',
      qty: '100',
      side: 'buy',
      symbol: 'QQQJ',
      leaves_qty: '131',
      order_id: 'ee8058e5-41a0-48fd-8156-915ae0af6d17',
      cum_qty: '869'
    },
    {
      id: '20210127144930176::b68ca618-f2a3-42a4-804f-f7ffda59023a',
      activity_type: 'FILL',
      transaction_time: '2021-01-27T19:49:30.176Z',
      type: 'partial_fill',
      price: '31.6',
      qty: '51',
      side: 'buy',
      symbol: 'QQQJ',
      leaves_qty: '30',
      order_id: 'ee8058e5-41a0-48fd-8156-915ae0af6d17',
      cum_qty: '970'
    },
    {
      id: '20210127144930176::0ef90479-4a4a-44e4-b7a2-a4186c0d7dfb',
      activity_type: 'FILL',
      transaction_time: '2021-01-27T19:49:30.176Z',
      type: 'fill',
      price: '31.6',
      qty: '30',
      side: 'buy',
      symbol: 'QQQJ',
      leaves_qty: '0',
      order_id: 'ee8058e5-41a0-48fd-8156-915ae0af6d17',
      cum_qty: '1000'
    },
    {
      id: '20210127144930176::0837a86c-26a5-4503-9367-c13730a7d0aa',
      activity_type: 'FILL',
      transaction_time: '2021-01-27T19:49:30.176Z',
      type: 'partial_fill',
      price: '31.6',
      qty: '50',
      side: 'buy',
      symbol: 'QQQJ',
      leaves_qty: '81',
      order_id: 'ee8058e5-41a0-48fd-8156-915ae0af6d17',
      cum_qty: '919'
    },
    {
      id: '20210127144930175::1a6ee896-6194-44a9-a603-24ec4e9fc87a',
      activity_type: 'FILL',
      transaction_time: '2021-01-27T19:49:30.175Z',
      type: 'partial_fill',
      price: '31.6',
      qty: '719',
      side: 'buy',
      symbol: 'QQQJ',
      leaves_qty: '231',
      order_id: 'ee8058e5-41a0-48fd-8156-915ae0af6d17',
      cum_qty: '769'
    },
    {
      id: '20210127144930175::01301eb9-48a3-4a91-9439-09f22d210c27',
      activity_type: 'FILL',
      transaction_time: '2021-01-27T19:49:30.175Z',
      type: 'partial_fill',
      price: '31.6',
      qty: '50',
      side: 'buy',
      symbol: 'QQQJ',
      leaves_qty: '950',
      order_id: 'ee8058e5-41a0-48fd-8156-915ae0af6d17',
      cum_qty: '50'
    }
]

As you can see, all these fills were for the same order, and happened within 2 milliseconds. The final fill appears in the middle of the list. The actual order can be unraveled by the cum_qty field.

Expected behavior If there is a ns-resolution timestamp in the back-end, maybe order by that, or by trade sequence, or something deterministic.

tr8dr commented 3 years ago

they should add a sequence # in these messages and make sure to order by seqno in the outgoing stream. I suspect they are using an unordered collection somewhere in their code.

I don't rely on cum_qty, rather accumulate fills I see. Of course if there is a bug where some fills are not reported, would be a problem.

spazmodius commented 3 years ago

I suspect it is ordered lexically by id, which is only approximately chronological.

PS--At one time the ids were discontinuous at 1pm Eastern each day. Hopefully that has been fixed.