Commit Graph

3376 Commits (d0ba9a0a587ff9815307179e288525304063b226)

Author SHA1 Message Date
Tyler Goodlet 77548d2ee6 Add token-from-user toggles to token auth methods 2019-02-25 20:11:45 -05:00
Tyler Goodlet 130553b8df Accept a path arg to `write()` 2019-02-25 19:29:54 -05:00
Tyler Goodlet 295ccbbe64 Name the data what it is 2019-02-24 10:55:52 -05:00
Tyler Goodlet c1a398d826 Use click context to factor cmd options 2019-02-23 16:13:04 -05:00
Tyler Goodlet 7ee731faac Use trio memory channels throughout UIs 2019-02-21 23:09:19 -05:00
Tyler Goodlet cbb973ae9d Drop internal nursery from option chain 2019-02-21 23:07:44 -05:00
Tyler Goodlet 462c419970 Add basic practice account support 2019-02-21 17:24:50 -05:00
Tyler Goodlet 435b2a56e8 Remove stream opening lock on `DataFeed`
Fixes to `tractor` that resolve issues with async generators being
non-task safe make the need for the mutex lock in
`DataFeed.open_stream()` unnecessary. Also, don't bother pushing empty
quotes from the publisher; avoids hitting the network when possible.
2019-02-20 21:39:57 -05:00
Tyler Goodlet 3a6efd451d Don't bother ensuring all symbols in data 2019-02-10 19:09:54 -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 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 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
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
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 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
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 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
Tyler Goodlet e1be80e9e0 Subscription teardown is done server side on disconnect now 2018-12-11 15:22:34 -05:00
Tyler Goodlet e7378538f6 Limit option chain to 1 rps 2018-12-11 15:21:45 -05:00
Tyler Goodlet 66ecb4c0cb Use a `trio.Event` to guarantee respawning of data feed task 2018-12-11 15:21:12 -05:00
Tyler Goodlet 01c0551a7f Don't display greeks besides delta for now 2018-12-11 15:20:24 -05:00
Tyler Goodlet 201919eef7 Initial option chain UI
Spin it up with `piker optschain`.
Still lots of polishing and features to add but it's a start!
2018-12-10 02:00:10 -05:00
Tyler Goodlet 8647216b75 Tabular kivy UI improvements
`Row`:
- `no_cell`: support a list of keys for which no cells will be created
- allow passing in a `cell_type` at instantiation

`TickerTable`:
- keep track of rendered rows via a private `_rendered` set
- don't create rows inside `append_row()` expect caller to do it
- never render already rendered widgets in `render_rows()`

Miscellaneous:
- generalize `update_quotes()` to not be tied to specific quote fields
  and allow passing in a quote `formatter()` func
- don't bother creating a nursery block until necessary in main
- more commenting
2018-12-10 01:51:49 -05:00
Tyler Goodlet 20778b02b5 Format numerical option fields 2018-12-10 01:50:00 -05:00
Tyler Goodlet 54261ecc4c Refer to async exit stack via feed 2018-12-10 01:49:19 -05:00
Tyler Goodlet fb47ea2e5a Define option field structure
Add some extra fields to each quote that QT should already be
providing (instead of hiding them in the symbol and request contract
info); namely, the expiry and contact type (i.e. put or call).
Define the base set of fields to be displayed in an option chain
UI and add a quote formatter.
2018-12-09 13:40:26 -05:00
Tyler Goodlet 9c7ca84fef Include strike and expiry in option quotes 2018-12-09 13:40:26 -05:00
Tyler Goodlet 9f3a316ccf Improve CPU usage using a clock trigger and deque
Copy out `kivy.clock.triggered` from version 1.10.1 since it isn't yet
available in the `trio`/async branch and use it to throttle the callback
rate. Use a `collections.deque` to LIFO iterate widgets each call
using the heuristic that it's more likely the mouse is still within the
currently highlighted (or it's adjacent neighbors) widget as opposed
to some far away widget (the case when the mouse is moved very
drastically across the window).
2018-12-09 13:39:38 -05:00
Tyler Goodlet b8815cde4a Set statespace defaults in `get_cached_feed()` 2018-12-09 13:30:34 -05:00
Tyler Goodlet eee19048f0 Support "mouse over" groups
Add a type factory func which returns mixin-able types for creating
mutex highlight-able groups of widgets.
2018-12-01 19:01:36 -05:00
Tyler Goodlet fd94a24d84 Rename to `mouse_over` 2018-12-01 18:43:44 -05:00
Tyler Goodlet 5c070b1c43 Faster highlighting via single loop and callback
Thanks yet again to @tshirtman for suggesting this.

Instead of defining a `on_mouse_pos()` on every widget simply
register and track each widget and loop through them all once (or as much
as is necessary) in a single callback. The assumption here is that we
get a performance boost by looping widgets instead of having `kivy` loop
and call back each widget thus avoiding costly python function calls.
2018-12-01 18:39:01 -05:00
Tyler Goodlet 7378a16b90 s/tickers/symbols 2018-12-01 16:12:46 -05:00
Tyler Goodlet 2915e83324 Warn about missing symbols at CLI level 2018-12-01 16:11:38 -05:00
Tyler Goodlet 61294c6c44 Adhere to the same non-found-symbol behaviour as QT 2018-12-01 16:09:41 -05:00
Tyler Goodlet f35671cc88 Handle bad symbol names 2018-12-01 16:08:03 -05:00
Tyler Goodlet 288ea604af Call start_quote_stream() from monitor main 2018-11-30 08:17:54 -05:00
Tyler Goodlet c2ec4800d6 Port cli to new options api 2018-11-30 08:16:31 -05:00
Tyler Goodlet cabc616b85 Port option api to new backend broker api 2018-11-30 08:14:36 -05:00
Tyler Goodlet c7cf0cde9c Add options streaming
Well that was a doozy; had to rejig pretty much all of it.

The deats:
- Track broker components in a new `DataFeed` namedtuple
- port to new list based batch quotes (not dicts any more)
- lock access to cached broker-client / data-feed instantiation
- respawn tasks that fail due to the network
2018-11-30 08:13:30 -05:00
Tyler Goodlet cd7d8d024d Add option quoter support for streaming
So much changed to get this working for both stocks and options:
- Index contracts by a new `ContractsKey` named tuple
- Move to pushing lists of quotes instead of dicts since option
  subscriptions are often not identified by their "symbol" key and
  this makes it difficult at fan out time to know how a quote should
  be indexed and delivered. Instead add a special `key` entry to each
  quote dict which is the quote's subscription key.
2018-11-30 00:33:40 -05:00
Tyler Goodlet 75d22c6058 An explicit name is prolly better 2018-11-25 19:23:07 -05:00
Tyler Goodlet 714c203c3e Cache symbol ids where possible
Cache both in the client and at the function call level inside the
quoter context using a `@afifo_cache`.
2018-11-25 15:00:08 -05:00
Tyler Goodlet af464b45ff Add an async function cache with a LIFO policy
Relates to #59
2018-11-25 14:55:55 -05:00
Tyler Goodlet a8a5e836b9 Use static instruction for highlighted row
Instead of all this adding/removing of canvas instructions nonsense
simple add a static "highlighted" rectangle to each row and make its
size very small when there's no mouse over.

Mad props to @tshirtman for showing me the light :D
2018-11-24 16:17:06 -05:00
Tyler Goodlet 488bdb34be Add mouse-over row highlighting 2018-11-23 22:21:53 -05:00
Tyler Goodlet a7f3008d34 Match the author's general apparel
It's still a bit of a shit show, and I've left a lot of commented tweaks
that need to be further played with, but I think this is a much
better look for what I'm considering to be one of the main "entry point"
apps for `piker`. To get any more serious fine tuning the way I want
I may have to talk to some kivy experts as I'm having some headaches
with button borders, padding, and the header row height..

Some of the new changes include:
- port to the new `brokers.data` module
- much darker theme with a stronger terminal vibe
- last trade price and volume amount flash on each trade
- fixed the symbol search bar to be a static height; before it was
  getting squashed oddly when using stacked windows
- make all the cells transparent (for now) such that I can just use
  a row color (relates to cell padding/spacing - can't seem to ditch it)
- start adding type annotations
2018-11-23 10:50:40 -05:00
Tyler Goodlet 0f3faec35d Reduce the scroll boundary bounce 2018-11-22 19:39:40 -05:00
Tyler Goodlet d102b82566 Don't add more then one stderr handler 2018-11-22 16:31:01 -05:00
Tyler Goodlet b9a9b7a9a3 Add options query and data feed recording commands
Add `contracts` and `optsquote` commands for querying option contracts
info and market quotes respectively. Add a `record` command for
streaming real-time data feed quotes to disk. Port `monitor` to the
new `piker.brokers.data` module. Forward loglevel flags through to
`tractor` for relevant commands.
2018-11-22 16:21:15 -05:00
Tyler Goodlet c23982393d Allow recording data feeds to disk
Add a couple functions for storing and retrieving live json data feed
recordings to disk using a very rudimentary character + newline delimited
format.

Also, split out the pub-sub logic from `stream_quotes()` into a new
func, `fan_out_to_chans()`. Eventually I want to formalize this pattern
into a decorator exposed through `tractor`.
2018-11-22 15:56:02 -05:00
Tyler Goodlet f038fdd42f Add a `contracts()` query
Makes it easy to request all the option contracts for a particular symbol.
Also, let `option_chain()` accept a `date` arg which can be used to only
retrieve quotes for a single expiry date (much faster then getting all
of them).
2018-11-22 15:53:00 -05:00
Tyler Goodlet 247bcb48c0 Tweak options query API method names 2018-11-22 09:19:04 -05:00
Tyler Goodlet 8fe0c40dde Move data feed machinery to separate module 2018-11-14 22:58:12 -05:00
Tyler Goodlet 31c69a5fae Allow specifying number of displayed digits 2018-11-13 18:42:34 -05:00
Tyler Goodlet 0c3bfb9e9e Stack the mktcap + volumes 2018-11-13 18:41:58 -05:00
Tyler Goodlet 6a66b056c8 Compact the look a bit 2018-11-13 18:41:40 -05:00
Tyler Goodlet 19ea7bd7aa Add option-chain cmd 2018-11-13 12:58:05 -05:00
Tyler Goodlet d145a5a219 Rejig option chain schema to capture all contracts 2018-11-13 12:57:21 -05:00
Tyler Goodlet f8d619b183 Go GPLv3 2018-11-12 00:29:43 -05:00
Tyler Goodlet 2b1818ba33 Drop old stream test, rename stock quote func 2018-11-11 21:45:11 -05:00
Tyler Goodlet a5afa0f1c3 Fix typo 2018-11-11 21:06:25 -05:00
Tyler Goodlet f9d9d7c1ba Add option chain quote support! 2018-11-11 21:05:30 -05:00
Tyler Goodlet 82c8fca983 Use tractor.run_daemon() for pikerd 2018-10-18 13:49:20 -04:00
Tyler Goodlet e108bc4521 Must pass a main async func to tractor 2018-09-05 18:31:10 -04:00
Tyler Goodlet 2349de8314 Rename watchlist app to 'monitor' 2018-08-23 23:12:39 -04:00
Tyler Goodlet 421cc4731f Face palm - fix mktcap sorting
Yuh think maybe the default "null" value shouldn't be a string...?

Fixes #46
2018-08-22 23:02:08 -04:00
Tyler Goodlet b2acfdaf42 Fix `pairs` type annotation 2018-08-22 23:01:34 -04:00
Tyler Goodlet 96b17e16ac Handle stale token case on network outage reconnect 2018-08-22 23:01:14 -04:00
Tyler Goodlet f3ac5e3c5f Port to latest tractor api 2018-08-09 21:54:02 -04:00
Tyler Goodlet 3efc7a4f77 Pass through loglevel to tractor 2018-07-06 17:26:45 -04:00
Tyler Goodlet 4427e2869c Cancel symbol unsub if brokerd is already down 2018-07-06 17:26:24 -04:00
Tyler Goodlet 6c977cfb7b Port broker core to tractor; fix chan unsub bug 2018-07-06 17:25:40 -04:00
Tyler Goodlet 31b8277f08 Drop tractor modules 2018-07-06 17:19:25 -04:00
goodboy 6ff871ff7d
Merge pull request #50 from pikers/tractor_draft
Introducing "tractor"
2018-07-05 15:52:53 -04:00
Tyler Goodlet f4a91a4975 Always do symbol unsubscribe on teardown 2018-07-05 15:31:52 -04:00
Tyler Goodlet 73eedfd7b3 Set tractor actor name at startup 2018-07-05 15:31:21 -04:00
Tyler Goodlet aa259433f5 Don't bother unsetting the squeue; let errors propogate up 2018-07-05 15:30:31 -04:00
Tyler Goodlet 0ac564dbf3 Only cancel channel spawned rpc tasks when explicitly notified 2018-07-05 15:27:02 -04:00
Tyler Goodlet e395845ddb Every ticker-chan subscription must include a caller id 2018-07-05 15:23:38 -04:00
Tyler Goodlet 5383dd6446 Add a working arbiter registry system
Every actor now registers (and unregisters) with the arbiter at
startup/teardown. For now the registry is stored in a plain `dict` in
the arbiter's memory. This makes it possible to easily coordinate actors
started as plain Python processes or via `multiprocessing`.

A whole smörgåsbord of changes was required to accomplish this:
- factor handshake steps into a func
- track *every* channel connected to an actor including multiples to the
  same remote peer (may want to optimize this later)
- handle `trio.ClosedStreamError` gracefully in the message loop
- add an `open_portal` asynccontextmanager which handles channel
  creation, handshaking, and spawning a bg task for msg processing
- add a `start_actor()` for starting in-process actors directly
- add working `get_arbiter()` and `find_actor()` public routines
- `_main` now tries an anonymous channel connect to the stated
  arbiter sockaddr and uses that to determine whether to crown itself
2018-07-04 14:34:25 -04:00
Tyler Goodlet 1d3fde4a4d Add StreamQueue.connected() 2018-07-04 03:16:00 -04:00
Tyler Goodlet ddf27e5e7f Cancel GUI updates on exit 2018-07-04 03:14:54 -04:00
Tyler Goodlet 23830d51d1 Log either kwarg 2018-06-27 11:59:02 -04:00
Tyler Goodlet 4ecfcdc354 Port `piker watch` to tractor api 2018-06-27 11:52:56 -04:00
Tyler Goodlet e22f17bfe9 Port watchlist app to tractor api 2018-06-27 11:50:02 -04:00
Tyler Goodlet 266518a734 Handle kb interrupt gracefully in sub-actors
Fail gracefully (by "aborting") the same way `trio` does. This avoids
ugly sub-proc tracebacks thrown at the console. Unset the local actor
when `tractor._main` completes. Cancel all tasks for a peer channel on
disconnect.
2018-06-27 11:34:22 -04:00
Tyler Goodlet 8019296c67 Port broker daemon to tractor
Drop all channel/connection handling from the core and break up all the
start up steps into compact and useful functions. The main difference is
the daemon now only needs to worry about spawning per broker streaming
tasks and handling symbol list subscription requests.
2018-06-26 17:55:52 -04:00
Tyler Goodlet c0d8d4fd99 Support re-entrant calls to `get_arbiter()`
It gets called more then once when using `tractor.run()` and
then `find_actor()`. Also, allow passing in the log level to each
new spawned subactor.
2018-06-25 17:41:30 -04:00
Tyler Goodlet 8c5af7fd97 Drop console logging - messes with other tests 2018-06-23 15:33:33 -04:00
Tyler Goodlet fa8418f97f Port stream_quotes to tractor ipc protocol 2018-06-23 14:57:02 -04:00
Tyler Goodlet 37eb8a8552 Fix actor nursery __exit__ handling
When an error is raised inside a nursery block (in the local actor)
cancel all spawned children and ensure the error is properly
unsuppressed.

Also,
- change `invoke_cmd` to `send_cmd` and expect the caller to use
  `result_from_q` (avoids implicit blocking for responses that might
  never arrive)
- `nursery.start()` the channel server block such that we wait for the
  underlying listener to spawn before making outbound connections
- cancel the channel server when an actor's main task completes
  (given that `outlive_main == False`)
- raise subactor errors directly in the local actors's msg loop
- enforce that `treat_as_gen` async functions respond with a caller id
  (`cid`) in each yield packet
2018-06-23 14:57:02 -04:00
Tyler Goodlet 84cd29644e Add reliable subactor lifetime control 2018-06-23 14:57:02 -04:00
Tyler Goodlet ef90d7f106 Add remote actor error handling and parent re-raising
Command requests are sent out and responses are handled in a "message
loop" where each command is associated with a "caller id" and multiple
cmds and results are multiplexed on the came inter-actor channel. When
a cmd result arrives it is pushed into a local queue and delivered to the
appropriate calling actor's task. Errors from a remote actor are always shipped
in an "error" packet back to their spawning-parent actor such that any error
in a subactor is always raised directly in the parent. Based on the
first response to a cmd (either a 'return' or 'yield' packet) the caller
side portal will retrieve values by wrapping the local response queue in
either of an async function or generator as appropriate.
2018-06-23 14:41:10 -04:00
Tyler Goodlet 75996fed0d Use trace level for packet contents 2018-06-23 14:40:49 -04:00
Tyler Goodlet b908bd0b9d Add uid,event attrs to `Channel` 2018-06-23 14:40:49 -04:00
Tyler Goodlet fa0aefff4d Take that QT nulls 2018-06-12 15:33:11 -04:00
Tyler Goodlet bf2f6769fc Uhhh make everything better 2018-06-12 15:17:48 -04:00
Tyler Goodlet 58f0182d8f Add a very rough, minimal actor model system
I'm calling it `tractor` (as in trio-actor) for now.
Lots of work to do still as per the many comments!

Relates to #27
2018-06-07 00:26:49 -04:00
Tyler Goodlet 28eff7122d Use `Channel` throughout cli entry point 2018-06-07 00:26:21 -04:00
Tyler Goodlet f71f986dae Use new IPC apis throughout core
Move to using `Channel` throughout instead of the `StreamQueue`
and add a very basic function for upcoming actor model testing.
2018-06-07 00:23:11 -04:00
Tyler Goodlet 2f82db33f4 IPC primitives improvements
- Rename the `Client` to `Channel`
- Add better `__repr__()`
- use laddr, raddr instead of sockaddr, peer
- don't allow re-entrant `Channel.connect()` calls
- Make `Channel` an async iterable
2018-06-07 00:19:31 -04:00
Tyler Goodlet 485aa76ff6 Move ipc types into separate module 2018-05-30 12:36:23 -04:00
Tyler Goodlet 2e5cdbcb7c Adjust to new modules 2018-05-30 09:37:53 -04:00
Tyler Goodlet 7e5e3c4cc6 Adjust reconnect coro to swallow symbol data resp
Couple fixes here:
- if no tickers for a watchlist name -> bail
- swallow the symbol data response in the reconnect handler coro
- don't sleep 5 seconds before connecting to subproc daemon...

Resolves #43
2018-05-17 13:20:21 -04:00
Tyler Goodlet a05a8cc557 Include process name in log messages 2018-05-16 20:39:47 -04:00
Tyler Goodlet 84fadf7ac4 Explicitly subscribe for tickers at wl startup 2018-05-16 20:33:44 -04:00
Tyler Goodlet 186befc704 Only run 'startup sequence' on reconnect
When a client loses a connection it will currently need to re-subscribe
for symbols and receive a symbol data summary as a first quote response.
Only run the provided coroutine on reconnect and call the kwarg
`on_reconnect`. The client consuming code is entirely expected at this
point to know how the symbol registration protocol works.
2018-05-16 19:15:43 -04:00
Tyler Goodlet 9b34aac0fd Build columns only for dataframe output 2018-05-09 18:09:04 -04:00
Tyler Goodlet bcaef70612 Pack null results without raising 2018-05-09 18:09:04 -04:00
Tyler Goodlet fd1fe0816e Don't call formatting func on None values 2018-05-09 18:09:04 -04:00
Tyler Goodlet 3646fb4a23 Filter out bad symbols before adding client subscription
Event if a broker client is already spawned new clients should still
receive a detailed symbol data packet as the first response. Avoid
exposing the new client's queue to the broker (i.e. subscribing it for
quotes) until after first pushing this packet with all bad symbols
filtered out.
2018-05-09 18:09:04 -04:00
Tyler Goodlet 3a40c2f8fe Zero bad fields 2018-05-09 18:09:04 -04:00
Tyler Goodlet 995851360d Rx symbol data from daemon as first response 2018-05-09 18:09:04 -04:00
Tyler Goodlet fcaeeae618 Acquire symbol data with daemon; push as first response 2018-05-09 18:09:04 -04:00
Tyler Goodlet 5a9c079c10 Support specifying daemon host address 2018-05-09 18:09:00 -04:00
Tyler Goodlet 3d6b14ec3f Pass in the host addr 2018-05-08 15:07:13 -04:00
Tyler Goodlet 7aa99019cb Allow adding multiple tickers via CLI 2018-04-25 09:10:57 -04:00
Tyler Goodlet 482f9531ca Try to connect to daemon once on startup; don't poll 2018-04-22 13:27:41 -04:00
Tyler Goodlet a2c4f0c80b Don't recurse in Client.aiter_recv() 2018-04-22 12:48:35 -04:00
Tyler Goodlet 6a6f773477 Adjust some log levels 2018-04-20 13:18:35 -04:00
Tyler Goodlet 063dfad5b4 Make daemon registry cross-task 2018-04-20 13:18:35 -04:00
Tyler Goodlet 4f387ea2be Fix subscriptions and connection handling
Oh boy where to start.

- Handle broken streams in the `StreamQueue` gracefully; terminate the
  async generator.
- When a stream queue connection is unwritable discard its subscriptions
  inside the quoter task
- If all subscriptions are discarded for a broker then tear down its
  quoter task
- Use listener parent nursery for spawning quoter tasks
- Make broker subs data structures global/shared between conn
  handler tasks
- Register the `tickers2qs` entry *after* instantiating broker client(s)
  (avoids race condition when mulitple client connections are coming
  online simultaneously)
- Push smoke quotes to every client not just the first that connects
- Track quoter tasks in a cross-task set
- Handle unsubscriptions more correctly
2018-04-20 13:18:35 -04:00
Tyler Goodlet 0add443e8b Spawn broker-daemon without asking 2018-04-20 13:18:35 -04:00
Tyler Goodlet 2973b40946 Allow wl app to spawn a broker daemon in a subprocess 2018-04-20 13:18:35 -04:00
Tyler Goodlet 90e8dd911c Daemon main doesn't require brokermod anymore 2018-04-20 13:18:35 -04:00
Tyler Goodlet 4123139750 Use `Client` in watchlist app 2018-04-20 13:18:35 -04:00
Tyler Goodlet 17feb17535 Add a reliable `Client` API
In order to start working toward a HA distributed
architecture make apps use a `Client` type to talk to daemons.
The `Client` provides fault-tolerance for connection failures such
that the app will continue running until a connection to the original
service can be made or the process is killed. This will make it easier
to simply spawn up new daemon child processes when faults are detected.
2018-04-20 13:18:35 -04:00
Tyler Goodlet 51b44cf236 Use msgpack for quote-packet serialization 2018-04-20 11:43:14 -04:00
Tyler Goodlet dd5e1e7ea7 Doh, set sleeptime after adjusting the rate limit 2018-04-20 11:43:14 -04:00
Tyler Goodlet 030ecdcce8 Filter symbols and push initial quote in stream handler
Filter out bad symbols by processing an initial batch quote and
pushing to the subscribing client before spawning a quoter task.
This also avoids exposing the quoter task to anything but the
broker module and a `get_quotes()` routine.
2018-04-20 11:43:14 -04:00
Tyler Goodlet 02a71c51ba Make <brokermod>.quoter() a simple factory func 2018-04-20 11:43:14 -04:00
Tyler Goodlet a6dc697327 Move watchlist app to new daemon-socket api 2018-04-20 11:43:14 -04:00
Tyler Goodlet 0c7ecd383b Monkey patch broker mods with a name attr 2018-04-20 11:43:14 -04:00
Tyler Goodlet 6359623019 Allow broker specific subscriptions
Allow client connections to subscribe for quote streams from specific
brokers and spawn broker-client quoter tasks on-demand according
to client connection demands. Support multiple subscribers to a
single daemon process.
2018-04-20 11:43:14 -04:00
Tyler Goodlet f80735121c Use an async generator inside `StreamQueue`
Async generators are faster and less code. Handle segmented packets
which can happen during periods of high quote volume. Move per-broker
rate limit logic into daemon task.
2018-04-20 11:43:14 -04:00
Tyler Goodlet 4898459bcd Make watchlist app retrieve quotes from the broker daemon 2018-04-20 11:43:14 -04:00
Tyler Goodlet 73ef95f42a Add `pikerd` entry point 2018-04-20 11:43:14 -04:00
Tyler Goodlet 23ae71089f Handle dynamic symbol subscriptions in QT backend 2018-04-20 11:42:59 -04:00
Tyler Goodlet d65bd78f5d Add a quote stream server task
Add a daemon-server task for delivering subscription based
quote streams via json serialized packets wrapped in a queue
interface.
2018-04-16 02:03:22 -04:00
Tyler Goodlet 577ca43c02 Include built-in lists in show, log errors from remove 2018-04-10 14:13:00 -04:00
Tyler Goodlet 381df2815d Expose remove errors to caller 2018-04-10 14:12:06 -04:00
Tyler Goodlet 6b72d04427 Change watchlist write function name 2018-04-06 15:07:47 -04:00
Tyler Goodlet 7e92df4352 Move built-in lists to respective module 2018-04-06 15:00:11 -04:00
Tyler Goodlet 0cccdd01b5 Only log when the network first goes down 2018-04-05 23:15:24 -04:00
K0nstantine 918133f265 Finalize WL Management and fix merge func 2018-04-04 00:35:12 -04:00
K0nstantine 49b760673e Remove write to file from API and move to CLI 2018-04-04 00:35:12 -04:00
K0nstantine cd69c30143 CLI tests for watchlist commands 2018-04-04 00:35:12 -04:00
K0nstantine 11f25958ba Move watchlist api tests to seperate module 2018-04-04 00:34:42 -04:00
K0nstantine e859222df4 Add initial API test, need relocation 2018-04-04 00:25:34 -04:00
K0nstantine d28a3dc461 Add initial config dir test 2018-04-04 00:25:34 -04:00
K0nstantine ce75bd8f6f Update CLI and create watchlists module
Moved the watchlists management implementation to a seperate module
wrapped in an api.

Resolves: #5
2018-04-04 00:25:34 -04:00
K0nstantine 43fbea5722 Sorted values and keys in watchlist dictionary and added a purge function 2018-04-04 00:25:34 -04:00
K0nstantine 7ada8a291e Initial watchlist management cli 2018-04-04 00:25:34 -04:00
Tyler Goodlet e246823f2d Add timeout handling to network poll loop 2018-04-02 14:51:38 -04:00
Tyler Goodlet 01cfbbdd64 Handle network outages
Quote queries will hang indefinitely when the network goes down.
Instead poll for network reestablishment such that roaming on
wifi is supported and real-time feeds will resume once the network is
back.
2018-03-31 12:02:22 -04:00
Tyler Goodlet 2b51e84a3c Expect quotes dict in watchlist update loop 2018-03-29 13:02:03 -04:00
Tyler Goodlet 164d636c67 Handle defunct QT tickers and delays 2018-03-29 13:01:13 -04:00
Tyler Goodlet 823bd2ea29 Make payload a ticker dict 2018-03-29 13:00:48 -04:00
Tyler Goodlet 9667042fe2 Drop NUU it's now just APH 2018-03-28 14:00:17 -04:00
Tyler Goodlet 801b9f860b Use `symbol_data()` in watclist UI 2018-03-27 16:27:55 -04:00
Tyler Goodlet 19303cf0ad Use brokermod util functions in cli 2018-03-27 16:27:30 -04:00
Tyler Goodlet 8544c22cdc Change `Client.symbols()` to `symbol_data()`
Make `symbol_data()` a common backend API method for looking up
auxiliary ticker/symbol data from brokers. It seems most have such
a call/endpoint.
2018-03-27 16:24:57 -04:00
Tyler Goodlet 8fc74c5085 Drop QT error 2018-03-27 16:16:31 -04:00
Tyler Goodlet 49d290d036 Add brokermod loader utils 2018-03-27 16:03:01 -04:00
Tyler Goodlet 29ddfe017c Use total time calc 2018-03-23 16:15:56 -04:00
Tyler Goodlet 178e091f41 Make robinhood the default broker backend
- Add a rate limit cli option
- Allow broker backends to define a max quote query limit
- Add an index ETF list to demonstrate robinhood's real-time prices
2018-03-21 17:28:40 -04:00
Tyler Goodlet 200526da8a Query QT at most 3 quotes/sec to avoid rate limits 2018-03-21 17:28:26 -04:00
Tyler Goodlet 933fe980c1 Set default quote rate to 5/sec 2018-03-21 17:27:04 -04:00
Tyler Goodlet 1ea784558c Pass through rate arg to `poll_tickers` 2018-03-21 17:26:30 -04:00
Tyler Goodlet 456e86990f Make watchlist app broker agnostic 2018-03-21 10:44:05 -04:00
Tyler Goodlet 6b47130c77 Move quote formatting to broker backends 2018-03-21 10:30:43 -04:00
Tyler Goodlet f0149118e1 Specify bid-ask "stacked" cells by argument 2018-03-20 21:20:55 -04:00
Tyler Goodlet 6c0f1fbdfc Fill failed symbol lookup df row with NaNs 2018-03-20 21:02:59 -04:00
Tyler Goodlet 48fe280e0c Return None on failed symbol lookups 2018-03-20 21:01:55 -04:00
Tyler Goodlet 04fa3c7ca4 Factor out QT quoting specifics into the backend 2018-03-20 15:39:49 -04:00
Tyler Goodlet 42e9296b36 Adjust cli to new backend api 2018-03-20 13:28:24 -04:00
Tyler Goodlet e75f0718a5 Add a basic quotes-only robinhood backend
We need a yank to test the order system and other end points that
require auth.

Resolves #2
2018-03-20 13:26:12 -04:00
Tyler Goodlet bd7eb16ab2 Move core tasks to separate module
Begin abstracting out broker backends by moving core data query tasks
into a module which requires and calls a broker backend API.
2018-03-20 13:13:07 -04:00
Tyler Goodlet 56f38263be Stack VWAP over daily high/low 2018-03-14 14:00:24 -04:00
goodboy d2e1605bf0
Merge pull request #14 from pikers/searchbar
Searchbar
2018-03-07 23:52:32 -05:00
Tyler Goodlet 937285d35c Add example watchlist your dad would want 2018-03-07 23:50:47 -05:00
Tyler Goodlet 2f34d982bc Require symbol info for quote processing 2018-03-06 20:54:37 -05:00
K0nstantine 61206f5903 Fix issue where config dir was not created by default
Fixes #15
2018-03-05 19:15:10 -05:00
Tyler Goodlet 7f3ee8c728 Add really basic ticker search bar 2018-03-05 09:26:52 -05:00
Tyler Goodlet 1e7dc38a50 Drop row factories; add ticker search API 2018-03-05 09:26:52 -05:00
Tyler Goodlet fc45e1215d Rename as pager mod 2018-03-05 09:26:52 -05:00
goodboy 09b16bf3e7
Merge pull request #13 from pikers/kb_ctls
Pager support
2018-03-04 21:58:16 -05:00
Tyler Goodlet 80ee1bfc19 Poll at 3 r/s and add more detailed timing logs 2018-03-02 21:24:09 -05:00
Tyler Goodlet 13e4389c9f Handle expired tokens more reliably; trace log json data 2018-02-22 18:44:46 -05:00
Tyler Goodlet 4b59b87f98 Add convenience methods for all log levels 2018-02-22 18:44:00 -05:00
Tyler Goodlet 6e0209ac6b Add pager support to watchlist 2018-02-22 18:39:21 -05:00
Tyler Goodlet 385f1b9607 Add a pager widget
It's a `ScrollView` but with keyboard controls that allow for paging
just like the classic unix `less` program. Add a search bar widget too!
2018-02-22 18:38:50 -05:00
Tyler Goodlet 9e0f58ea6b Add a keyboard input handling task 2018-02-17 15:09:22 -05:00
Tyler Goodlet ff437ce9e1 Handle out of process token refreshes 2018-02-15 16:40:33 -05:00
Tyler Goodlet b41b262b7d Raise any unexpected error 2018-02-14 18:49:58 -05:00
Tyler Goodlet d50aa17a83 Add real-time market caps 2018-02-14 12:06:54 -05:00
Tyler Goodlet 722d294915 Handle non-numbers in `humanize()` 2018-02-14 12:06:29 -05:00
Tyler Goodlet 722b515246 Limit humanize output to 2 decimal places 2018-02-14 02:43:55 -05:00
Tyler Goodlet e464898210 Combine last,bid,ask in a StackLayout-cell 2018-02-14 02:37:26 -05:00
Tyler Goodlet 29be7f58c9 Push every new change; not just the last trade 2018-02-13 15:57:12 -05:00
Tyler Goodlet 62bac7b2cd Don't sleep on less than zero delay 2018-02-13 12:13:27 -05:00
Tyler Goodlet 472ff68811 Fix row header highlight typo 2018-02-13 12:13:27 -05:00
Tyler Goodlet f31ebe6fcd Handle numbers of magnitude 2 2018-02-13 12:13:19 -05:00
Tyler Goodlet e4ff113dfc Sort rows by column on click 2018-02-13 10:34:24 -05:00
Tyler Goodlet 8e577cd0d0 Use lighter red; sort rows on startup 2018-02-12 16:11:31 -05:00
Tyler Goodlet 274a5a728a Fix row header borders using a `BorderImage` 2018-02-12 16:02:11 -05:00
Tyler Goodlet 1bbf212ad0 Work when only newly time stamped quotes are received 2018-02-12 14:05:57 -05:00
Tyler Goodlet b7b7abbc1f Only push new quotes to the queue at 5 per sec 2018-02-12 14:03:31 -05:00
Tyler Goodlet 9f3efd2a6a Import client for now until we make a proper shim 2018-02-12 10:35:54 -05:00
Tyler Goodlet f4fd35fa21 Separate sortable and dislplayable quote values 2018-02-10 19:54:09 -05:00
Tyler Goodlet 488f3988ea Handle weekend errors 2018-02-10 19:44:41 -05:00
Tyler Goodlet 1af14bc46f Add watchlist sort-by-column and row header highlighting 2018-02-09 22:04:53 -05:00
Tyler Goodlet 0997418a47 Be PC 2018-02-09 22:01:14 -05:00
Tyler Goodlet 37a4d2e5f8 Expose watchlist app via `piker watch` for now 2018-02-09 03:29:30 -05:00
Tyler Goodlet e220e9b658 Move cli mod to top level package 2018-02-09 03:01:58 -05:00
Tyler Goodlet f71391252d Tighten up the UI to be super sleek 2018-02-09 02:44:43 -05:00
Tyler Goodlet e45c07dce7 Watchlist fixes
- make the % daily change use the previous days close as the reference
  price
- color each cell on every change (results in "pulsed" colors on changes)
- tweak some quote fields
- redraw and sort all rows on every quotes update cycle
- error when the QT api is returning None values
2018-02-08 19:30:09 -05:00
Tyler Goodlet 17c4ac3b8c Adjust cli to new api 2018-02-08 19:15:21 -05:00
Tyler Goodlet 224451f44a Make ticker stream caching optional
Push all ticker quotes to the queue regardless of duplicate
content. That is, don't worry about only pushing new quote changes
(turns out it is useful when coloring a watchlist where multiple
of the same quote may indicate multiple similar trades and we only
want to quickly "pulse" color changes on value changes).
If it is desired to only push new changes, the ``cache`` flag enables
the old behaviour.

Also add `Client.symbols()` for returning symbol data from a sequence of
tickers.
2018-02-08 19:10:17 -05:00
Tyler Goodlet 13342c459a Our first real-time watchlist! 2018-02-08 02:39:18 -05:00
Tyler Goodlet b8a3fb67a1 Add a quote-from-json-file streamer for testing 2018-02-08 02:39:18 -05:00
Tyler Goodlet 6781a23850 Add a `quote` subcommand
Add `piker quote <tickerA> <tickerB> <tickerC>` command for easily
dumping quote data to the console. With `-df` will dump as a pandas data
frame. Add key filtering to `piker api` calls.
2018-02-08 02:39:18 -05:00
Tyler Goodlet adecc082ac Save `brokers.ini` in the user config dir using click 2018-02-08 02:39:18 -05:00
Tyler Goodlet 151e7bf4fa More client enhancements
- Extend the qt api to include candles (not working yet), balances, positions.
- Add a `quote()` method to the `Client` for batch ticker quotes and expose
  it through a CLI subcommand.
- Make `poll_tickers` push new quotes to a `trio.Queue`
2018-02-08 02:39:18 -05:00
Tyler Goodlet 797efedf6a Add quote polling; pseudo-streaming
Add a ``poll_tickers`` coro which can be used to "stream" quotes at
a requested rate. Expose through a cli subcommand `piker stream`.
Drop the `pikerd` command for now.
2018-01-29 12:45:48 -05:00
Tyler Goodlet 66441d15e8 Complain when kwargs are missing but required 2018-01-27 01:52:00 -05:00
Tyler Goodlet 1b93a4c02a Add an `api` cli subcommand for console testing
Add `piker api <method> <kwargs>` for easy testing of the
underlying broker api from the console.
2018-01-26 14:31:15 -05:00
Tyler Goodlet 27a39ac3ad More client improvements
- colorize json response data in logs
- support ``refresh_token`` retrieval from user if the token for some
  reason expires while the client is live
- extend api method support for markets, search, symbols, and quotes
- support "proxying" through api calls via an ``api`` coro for one off
  client queries (useful for cli testing)
2018-01-26 14:25:53 -05:00
Tyler Goodlet 534ba0b698 Add json highlighting; make debug msgs white 2018-01-26 11:31:40 -05:00
Tyler Goodlet 9e8ed392d4 Add token refresher task 2018-01-25 21:53:55 -05:00
Tyler Goodlet 4e1c64a7fb Import broker backend by name 2018-01-25 21:08:49 -05:00
Tyler Goodlet c6cff5a432 Swap debug-garbage log colours 2018-01-25 20:59:56 -05:00
Tyler Goodlet 5c4996873a Start using click for cli 2018-01-25 20:56:57 -05:00
Tyler Goodlet 1b0269e51a Drop `Client.from_config()` factory - more cleanups 2018-01-25 20:56:57 -05:00
Tyler Goodlet e45cdf92f0 Log entire access config on exit 2018-01-25 20:56:57 -05:00
Tyler Goodlet c7258f3fb2 Build bold palette automatically 2018-01-22 22:05:42 -05:00
Tyler Goodlet 570d879146 Save tokens locally for use across runs
Store tokens in a local config file avoiding any refresh delay
unless necessary when the current access token expires.

Summary:
- move draft main routine into the `brokers` package mod
- start an api wrapper type
- always write the current access tokens to the config on teardown
2018-01-22 22:05:42 -05:00
Tyler Goodlet e312fb6525 Add config for saving access creds between runs 2018-01-22 22:05:42 -05:00
Tyler Goodlet 9745e16cf2 Drop userdata; use a dict 2018-01-22 22:05:42 -05:00
Tyler Goodlet 5a6b7510f8 Initial user account access using trio + asks 2018-01-22 22:05:42 -05:00
Tyler Goodlet 15fe580326 Super hot hipster logging 2018-01-22 22:05:42 -05:00