Merge pull request #321 from pikers/ib_dedicated_data_client

Ib dedicated data client
flexxin
goodboy 2022-06-05 22:12:46 -04:00 committed by GitHub
commit be7c4e70f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 719 additions and 560 deletions

View File

@ -12,16 +12,34 @@ api_key = ""
secret = ""
[ib]
host = "127.0.0.1"
hosts = [
"127.0.0.1",
]
# XXX: the order in which ports will be scanned
# (by the `brokerd` daemon-actor)
# is determined # by the line order here.
# TODO: when we eventually spawn gateways in our
# container, we can just dynamically allocate these
# using IBC.
ports = [
4002, # gw
7497, # tws
]
ports.gw = 4002
ports.tws = 7497
ports.order = ["gw", "tws",]
# when clients are being scanned this determines
# which clients are preferred to be used for data
# feeds based on the order of account names, if
# detected as active on an API client.
prefer_data_account = [
'paper',
'margin',
'ira',
]
accounts.margin = "X0000000"
accounts.ira = "X0000000"
accounts.paper = "XX0000000"
# the order in which accounts will be selected (if found through
# `brokerd`) when a new symbol is loaded
accounts_order = ['paper', 'margin', 'ira']
[ib.accounts]
# the order in which accounts will be selectable
# in the order mode UI (if found via clients during
# API-app scanning)when a new symbol is loaded.
paper = "XX0000000"
margin = "X0000000"
ira = "X0000000"

View File

@ -13,4 +13,4 @@ x11vnc \
-autoport 3003 \
# can't use this because of ``asyncvnc`` issue:
# https://github.com/barneygale/asyncvnc/issues/1
# -passwd "$VNC_SERVER_PASSWORD"
# -passwd 'ibcansmbz'

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,7 @@ import numpy as np
from ..brokers import get_brokermod
from .._cacheables import maybe_open_context
from ..calc import humanize
from ..log import get_logger, get_console_log
from .._daemon import (
maybe_spawn_brokerd,
@ -1183,10 +1184,10 @@ class Feed:
shm: ShmArray
mod: ModuleType
first_quotes: dict # symbol names to first quote dicts
_portal: tractor.Portal
stream: trio.abc.ReceiveChannel[dict[str, Any]]
status: dict[str, Any]
throttle_rate: Optional[int] = None
_trade_stream: Optional[AsyncIterator[dict[str, Any]]] = None
@ -1327,9 +1328,24 @@ async def open_feed(
first_quotes=first_quotes,
stream=stream,
_portal=portal,
status={},
throttle_rate=tick_throttle,
)
# fill out "status info" that the UI can show
host, port = feed.portal.channel.raddr
if host == '127.0.0.1':
host = 'localhost'
feed.status.update({
'actor_name': feed.portal.channel.uid[0],
'host': host,
'port': port,
'shm': f'{humanize(feed.shm._shm.size)}',
'throttle_rate': feed.throttle_rate,
})
feed.status.update(init_msg.pop('status', {}))
for sym, data in init_msg.items():
si = data['symbol_info']
fqsn = data['fqsn'] + f'.{brokername}'

View File

@ -0,0 +1,83 @@
# piker: trading gear for hackers
# Copyright (C) Tyler Goodlet (in stewardship for piker0)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
Feed status and controls widget(s) for embedding in a UI-pane.
"""
from __future__ import annotations
from textwrap import dedent
from typing import TYPE_CHECKING
# from PyQt5.QtCore import Qt
from ._style import _font, _font_small
# from ..calc import humanize
from ._label import FormatLabel
if TYPE_CHECKING:
from ._chart import ChartPlotWidget
from ..data.feed import Feed
from ._forms import FieldsForm
def mk_feed_label(
form: FieldsForm,
feed: Feed,
chart: ChartPlotWidget,
) -> FormatLabel:
'''
Generate a label from feed meta-data to be displayed
in a UI sidepane.
TODO: eventually buttons for changing settings over
a feed control protocol.
'''
status = feed.status
assert status
msg = dedent("""
actor: **{actor_name}**\n
|_ @**{host}:{port}**\n
""")
for key, val in status.items():
if key in ('host', 'port', 'actor_name'):
continue
msg += f'\n|_ {key}: **{{{key}}}**\n'
feed_label = FormatLabel(
fmt_str=msg,
# |_ streams: **{symbols}**\n
font=_font.font,
font_size=_font_small.px_size,
font_color='default_lightest',
)
# form.vbox.setAlignment(feed_label, Qt.AlignBottom)
# form.vbox.setAlignment(Qt.AlignBottom)
_ = chart.height() - (
form.height() +
form.fill_bar.height()
# feed_label.height()
)
feed_label.format(**feed.status)
return feed_label

View File

@ -750,12 +750,12 @@ def mk_order_pane_layout(
parent=parent,
fields_schema={
'account': {
'label': '**account**:',
'label': '**accnt**:',
'type': 'select',
'default_value': ['paper'],
},
'size_unit': {
'label': '**allocate**:',
'label': '**alloc**:',
'type': 'select',
'default_value': [
'$ size',

View File

@ -30,6 +30,7 @@ import uuid
from pydantic import BaseModel
import tractor
import trio
from PyQt5.QtCore import Qt
from .. import config
from ..clearing._client import open_ems, OrderBook
@ -37,6 +38,7 @@ from ..clearing._allocate import (
mk_allocator,
Position,
)
from ._style import _font
from ..data._source import Symbol
from ..data.feed import Feed
from ..log import get_logger
@ -46,7 +48,8 @@ from ._position import (
PositionTracker,
SettingsPane,
)
from ._label import FormatLabel
from ._forms import FieldsForm
# from ._label import FormatLabel
from ._window import MultiStatus
from ..clearing._messages import Order, BrokerdPosition
from ._forms import open_form_input_handling
@ -639,63 +642,21 @@ async def open_order_mode(
pp_tracker.hide_info()
# setup order mode sidepane widgets
form = chart.sidepane
vbox = form.vbox
from textwrap import dedent
from PyQt5.QtCore import Qt
from ._style import _font, _font_small
from ..calc import humanize
feed_label = FormatLabel(
fmt_str=dedent("""
actor: **{actor_name}**\n
|_ @**{host}:{port}**\n
|_ throttle_hz: **{throttle_rate}**\n
|_ streams: **{symbols}**\n
|_ shm: **{shm}**\n
"""),
font=_font.font,
font_size=_font_small.px_size,
font_color='default_lightest',
)
form.feed_label = feed_label
# add feed info label to top
vbox.insertWidget(
0,
feed_label,
alignment=Qt.AlignBottom,
)
# vbox.setAlignment(feed_label, Qt.AlignBottom)
# vbox.setAlignment(Qt.AlignBottom)
_ = chart.height() - (
form.height() +
form.fill_bar.height()
# feed_label.height()
)
vbox.setSpacing(
form: FieldsForm = chart.sidepane
form.vbox.setSpacing(
int((1 + 5/8)*_font.px_size)
)
# fill in brokerd feed info
host, port = feed.portal.channel.raddr
if host == '127.0.0.1':
host = 'localhost'
mpshm = feed.shm._shm
shmstr = f'{humanize(mpshm.size)}'
form.feed_label.format(
actor_name=feed.portal.channel.uid[0],
host=host,
port=port,
symbols=len(feed.symbols),
shm=shmstr,
throttle_rate=feed.throttle_rate,
from ._feedstatus import mk_feed_label
feed_label = mk_feed_label(
form,
feed,
chart,
)
# XXX: we set this because?
form.feed_label = feed_label
order_pane = SettingsPane(
form=form,
# XXX: ugh, so hideous...
@ -706,6 +667,11 @@ async def open_order_mode(
)
order_pane.set_accounts(list(trackers.keys()))
form.vbox.addWidget(
feed_label,
alignment=Qt.AlignBottom,
)
# update pp icons
for name, tracker in trackers.items():
order_pane.update_account_icons({name: tracker.live_pp})

View File

@ -15,3 +15,7 @@
# ``trimeter`` for asysnc history fetching
-e git+https://github.com/python-trio/trimeter.git@master#egg=trimeter
# ``asyncvnc`` for sending interactions to ib-gw inside docker
-e git+https://github.com/pikers/asyncvnc.git@vid_passthrough#egg=asyncvnc