Commit Graph

2899 Commits (4eea8042ffdb91af2a5fa3c9a222c6451403d63a)

Author SHA1 Message Date
Tyler Goodlet ea289540b3 Add a test to verify auth endpoint "locking" 2019-02-09 21:58:49 -05:00
Tyler Goodlet 3ab9e28ddb Use brokerd's client to get all contracts 2019-02-09 21:58:27 -05:00
Tyler Goodlet 395f0c8e4a Synchronize Questrade token refreshing per client
Questrade's API is half baked and can't handle concurrency.
It allows multiple concurrent requests to most endpoints *except*
for the auth endpoint used to refresh tokens:

    https://www.questrade.com/api/documentation/security

I've gone through extensive dialogue with their API team and despite
making what I think are very good arguments for doing the request
serialization on the server side, they decided that I should instead
do the "locking" on the client side. Frankly it doesn't seem like they
have that competent an engineering department as it took me a long time
to explain the issue even though it's rather trivial and probably not
that hard to fix; maybe it's better this way.

This adds a few things to ensure more reliable token refreshes on
expiry:

- add a `@refresh_token_on_err` decorator which can be used on `_API`
  methods that should refresh tokens on failure
- decorate most endpoints with this *except* for the auth ep
- add locking logic for the troublesome scenario as follows:
  * every time a request is sent out set a "request in progress" event
    variable that can be used to determine when no requests are currently
    outstanding
  * every time the auth end point is hit in order to refresh tokens set
    an event that locks out other tasks from making requests
  * only allow hitting the auth endpoint when there are no "requests in
    progress" using the first event
  * mutex all auth endpoint requests; there can only be one outstanding

- don't hit the accounts endpoint at client startup; we want to
  eventually support keys from multiple accounts and you can disable
  account info per key and just share the market data function
2019-02-09 21:39:22 -05:00
Tyler Goodlet f6230dd6df Add a `DataFeed.call_client()` method
Allows for calling an actor local broker client's methods from a remote
actor.
2019-02-09 21:38:00 -05:00
Tyler Goodlet 026b015627 Allow passing a config path for broker testing in CI 2019-02-04 00:17:11 -05:00
Tyler Goodlet 5339f754a1 Add a token refresh test that exhibits an API race issue 2019-02-04 00:16:16 -05:00
Tyler Goodlet 5dac8fa44d Note the RH auth/account requirements for usage 2019-02-04 00:15:10 -05:00
Tyler Goodlet e91a50a1ba Make `get_cached_feed()` an asynccontextmanager
Adjust feed locking around internal manager `yields` to make this work.

Also, change quote publisher to deliver a list of quotes for each
retrieved batch. This was actually broken for option streaming since
each quote was being overwritten due to a common `key` value for all
expiries. Asjust the `packetizer` function accordingly to work for
both options and stocks.
2019-02-03 23:40:51 -05:00
Tyler Goodlet 9b37607b04 Deps bump 2019-01-27 22:10:49 -05:00
Tyler Goodlet 2514843fc1 Port to the new `@tractor.msg.pub` decorator API
The pub-sub data feed system was factored into `tractor` as an
experimental api / subsystem. Move to using that which greatly
simplifies the data feed architecture.
2019-01-27 14:50:04 -05:00
Tyler Goodlet 22670afe58 Generalize the publisher/fan-out system
Start working toward a more general (on-demand) pub-sub system which
can be brought into ``tractor``. Right now this just means making
the code in the `fan_out_to_ctxs()` less specific but, eventually
I think this function should be coupled with a decorator and shipped
as a standard "message pattern".

Additionally,
- try out making `BrokerFeed` a `@dataclass`
- strip out all the `trio.Event` / uneeded nursery / extra task crap
  from `start_quote_stream()`
2019-01-14 21:23:49 -05:00
Tyler Goodlet c94ce47aa6 Always set contract sub state 2019-01-14 21:13:22 -05:00
Tyler Goodlet 4753dc2db8 Alway teardown quote gen on exit 2019-01-14 21:12:35 -05:00
goodboy 78dced3091
Merge pull request #64 from pikers/data_feed_reorg
Data feed reorg
2019-01-12 11:47:21 -05:00
Tyler Goodlet 36d0c2ed68 Port monitor app to `DataFeed` api 2019-01-05 19:08:31 -05:00
Tyler Goodlet a4501bb0e0 Factor `DataFeed` client API into `brokers.data` 2019-01-05 19:08:27 -05:00
goodboy e69f0b286c
Merge pull request #63 from pikers/options_ui
Options chain UI!
2019-01-02 21:34:15 -05:00
Tyler Goodlet 7f8c88be0c Drop open/close prices for now; never really use them 2019-01-02 21:24:42 -05:00
Tyler Goodlet fa6bae1f5c Reorg table widgets into a new module 2019-01-02 21:12:42 -05:00
Tyler Goodlet 4895690642 Display a message when no contracts exist 2019-01-01 23:42:49 -05:00
Tyler Goodlet 0cffa4b97a Font size shrinks 2019-01-01 23:36:46 -05:00
Tyler Goodlet 32a7f4cbd3 Right, gotta expose widgets to other actors 2018-12-31 11:51:04 -05:00
Tyler Goodlet 72f417b9c2 Support monitor linked symbol selection
This allows for using a monitor to select the current option chain
symbol!

The deats:
- start a bg task which streams the monitor selected symbol
- dynamically repopulate expiry buttons on a newly published symbol
- move static widget creation into a chain method to avoid multiple
  quotes requests at startup
- rename a bunch of methods
2018-12-30 15:00:46 -05:00
Tyler Goodlet 152062ba8a Support pub-sub of monitor's symbol selection 2018-12-30 14:59:54 -05:00
Tyler Goodlet 3ed750d324 Add contract table type headers 2018-12-29 16:01:07 -05:00
Tyler Goodlet b4fad3f6a9 Logic factoring 2018-12-29 16:00:18 -05:00
Tyler Goodlet 1866dd1812 Fix for adjusted contracts subscription bug
If quotes are pushed using the adjusted contract symbol (i.e. with
trailing '-1' suffix) the subscriber won't receive them under the
normal symbol. The logic was wrong for determining whether to add
a suffix (was failing for any symbol with an exchange suffix)
which was causing normal data feed subscriptions to fail to match
in every case.

I did some testing of the `optionsIds` parameter to the option quote
endpoint and found that it limits you to 100 symbols so it's not
practical for real-time "all-strike"" chain updating; we have to stick
to filters for now. The only real downside of this is that it seems
multiple filters across multiple symbols is quite latent. I need to
toy with it more to be sure it's not something slow on the client side.
Oh, and store option contract to ids in a `dict` for now as we may want
to try the `optionsIds` thing again down the road as I coordinate with
the QT tech team.
2018-12-29 15:44:32 -05:00
Tyler Goodlet dc581d0bdc Handle "adjusted contract" chains per root 2018-12-26 13:30:50 -05:00
Tyler Goodlet fb876f3770 Drop `OptionChain.start_feed()` 2018-12-25 12:38:04 -05:00
Tyler Goodlet 6cc8b4cc2f Test duplicate feed type quoting 2018-12-23 21:27:47 -05:00
Tyler Goodlet a7fb55179c Handle weekend data from QT yet again 2018-12-23 21:26:57 -05:00
Tyler Goodlet de4fab873b Ids should be allowed without contracts 2018-12-23 21:25:56 -05:00
Tyler Goodlet eb8c9e1a99 Symbol subs must be cid specific 2018-12-23 20:48:06 -05:00
Tyler Goodlet 11222e1176 Only resort when the sort field actually changed 2018-12-18 20:28:26 -05:00
Tyler Goodlet d4e36b1e55 Jeeze, don't overwrite the payload for each channel... 2018-12-17 19:15:29 -05:00
Tyler Goodlet 5af90c044f Drop contracts cache; that wasn't the bottleneck
This also fixes a bug where option subscriptions weren't actually being
changed when a new call was made..
2018-12-16 23:56:03 -05:00
goodboy b0d4d4b2f8
Merge pull request #61 from pikers/faster_highlighting
Faster row highlighting
2018-12-16 21:53:48 -05:00
Tyler Goodlet 3fd01c42f2 Define highlight on click logic in `Cell` 2018-12-15 19:42:15 -05:00
Tyler Goodlet 1f608b2498 Even less latent 2018-12-15 19:41:12 -05:00
Tyler Goodlet a13b13e144 Highlight current expiry; mutex data feed access 2018-12-15 19:40:54 -05:00
Tyler Goodlet 7ed409501d Even less bouncy 2018-12-15 16:38:33 -05:00
Tyler Goodlet 07eb8ae5e0 Use binary search (bisection) to sort table rows
This is an optimization to improve performance when the UI is fed real
time data. Instead of resorting all rows on every quote update, only
re-render when the sort key appears in the quote data, and further, only
resort rows which are changed using bisection based widget insertion to
avoid having `kivy` re-add widgets (and thus re-render graphics) more
often than absolutely necessary.
2018-12-15 16:28:28 -05:00
Tyler Goodlet 721e3803b2 Shorter title of IV: implied volatility 2018-12-15 16:27:41 -05:00
Tyler Goodlet 70435e3b15 Always push an option smoke quote for UI init 2018-12-15 16:26:54 -05:00
Tyler Goodlet e3a3a8765c Remove destroyed widgets from mouse over list 2018-12-15 16:26:21 -05:00
Tyler Goodlet 948ee3cadf Cache contracts lookup once at startup 2018-12-13 13:11:07 -05:00
Tyler Goodlet 9e4786e62f Initial dynamic option chain UI draft
There's still a ton to polish (and some bugs to fix) but this is a first
working draft of a real-time option chain!

Insights and todos:
- `kivy` widgets need to be cached and reused (eg. rows, cells, etc.)
  for speed since it seems creating new ones constantly is quite taxing
  on the CPU
- the chain will tear down and re-setup the option data feed stream each
  time a different contract expiry button set is clicked
- there's still some weird bug with row highlighting where it seems rows
  added from a new expiry set (which weren't previously rendered) aren't
  being highlighted reliably
2018-12-13 13:04:05 -05:00
Tyler Goodlet 1d1be9dd77 Include option stream subscription change in test 2018-12-11 17:10:36 -05:00
Tyler Goodlet 743ca6bfe3 Log quotes even without caching 2018-12-11 17:09:59 -05:00
Tyler Goodlet 7b5c73bb45 Use pythonic sequence splitting with `zip()` 2018-12-11 17:09:36 -05:00