Invert data provider's OHLCV field defs
Turns out the reason we were originally making the `time: float` column in our
ohlcv arrays was bc that's what **only** ib uses XD (and/or 🤦)
Instead we changed the default field type to be an `int` (which is also
more correct to avoid `float` rounding/precision discrepancies) and thus
**do not need to override it** in all other (crypto) backends (except
`ib`). Now we only do the customization (via `._ohlc_dtype`) to `float`
only for `ib` for now (though pretty sure we can also not do that
eventually as well..)!
basic_buy_bot
parent
af64152640
commit
9859f601ca
|
@ -58,9 +58,10 @@ from ._util import (
|
||||||
log,
|
log,
|
||||||
get_console_log,
|
get_console_log,
|
||||||
)
|
)
|
||||||
from ..data.types import Struct
|
from piker.data.types import Struct
|
||||||
from ..data.validate import FeedInit
|
from piker.data.validate import FeedInit
|
||||||
from ..data._web_bs import (
|
from piker.data import def_iohlcv_fields
|
||||||
|
from piker.data._web_bs import (
|
||||||
open_autorecon_ws,
|
open_autorecon_ws,
|
||||||
NoBsWs,
|
NoBsWs,
|
||||||
)
|
)
|
||||||
|
@ -70,30 +71,21 @@ _url = 'https://api.binance.com'
|
||||||
|
|
||||||
|
|
||||||
# Broker specific ohlc schema (rest)
|
# Broker specific ohlc schema (rest)
|
||||||
_ohlc_dtype = [
|
# XXX TODO? some additional fields are defined in the docs:
|
||||||
('index', int),
|
# https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
||||||
('time', int),
|
|
||||||
('open', float),
|
|
||||||
('high', float),
|
|
||||||
('low', float),
|
|
||||||
('close', float),
|
|
||||||
('volume', float),
|
|
||||||
('bar_wap', float), # will be zeroed by sampler if not filled
|
|
||||||
|
|
||||||
# XXX: some additional fields are defined in the docs:
|
|
||||||
# https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
|
||||||
|
|
||||||
|
# _ohlc_dtype = [
|
||||||
# ('close_time', int),
|
# ('close_time', int),
|
||||||
# ('quote_vol', float),
|
# ('quote_vol', float),
|
||||||
# ('num_trades', int),
|
# ('num_trades', int),
|
||||||
# ('buy_base_vol', float),
|
# ('buy_base_vol', float),
|
||||||
# ('buy_quote_vol', float),
|
# ('buy_quote_vol', float),
|
||||||
# ('ignore', float),
|
# ('ignore', float),
|
||||||
]
|
# ]
|
||||||
|
|
||||||
# UI components allow this to be declared such that additional
|
# UI components allow this to be declared such that additional
|
||||||
# (historical) fields can be exposed.
|
# (historical) fields can be exposed.
|
||||||
ohlc_dtype = np.dtype(_ohlc_dtype)
|
# ohlc_dtype = np.dtype(_ohlc_dtype)
|
||||||
|
|
||||||
_show_wap_in_history = False
|
_show_wap_in_history = False
|
||||||
|
|
||||||
|
@ -330,7 +322,7 @@ class Client:
|
||||||
bar.typecast()
|
bar.typecast()
|
||||||
|
|
||||||
row = []
|
row = []
|
||||||
for j, (name, ftype) in enumerate(_ohlc_dtype[1:]):
|
for j, (name, ftype) in enumerate(def_iohlcv_fields[1:]):
|
||||||
|
|
||||||
# TODO: maybe we should go nanoseconds on all
|
# TODO: maybe we should go nanoseconds on all
|
||||||
# history time stamps?
|
# history time stamps?
|
||||||
|
@ -343,7 +335,10 @@ class Client:
|
||||||
|
|
||||||
new_bars.append((i,) + tuple(row))
|
new_bars.append((i,) + tuple(row))
|
||||||
|
|
||||||
array = np.array(new_bars, dtype=_ohlc_dtype) if as_np else bars
|
array = np.array(
|
||||||
|
new_bars,
|
||||||
|
dtype=def_iohlcv_fields,
|
||||||
|
) if as_np else bars
|
||||||
return array
|
return array
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,43 +18,33 @@
|
||||||
Deribit backend.
|
Deribit backend.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import json
|
|
||||||
import time
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from contextlib import (
|
||||||
from contextlib import asynccontextmanager as acm, AsyncExitStack
|
asynccontextmanager as acm,
|
||||||
from functools import partial
|
)
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Optional, Iterable, Callable
|
from functools import partial
|
||||||
|
import time
|
||||||
import pendulum
|
from typing import (
|
||||||
import asks
|
Any,
|
||||||
import trio
|
Optional,
|
||||||
from trio_typing import Nursery, TaskStatus
|
Callable,
|
||||||
from fuzzywuzzy import process as fuzzy
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
from piker.data.types import Struct
|
|
||||||
from piker.data._web_bs import (
|
|
||||||
NoBsWs,
|
|
||||||
open_autorecon_ws,
|
|
||||||
open_jsonrpc_session
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from .._util import resproc
|
import pendulum
|
||||||
|
import trio
|
||||||
from piker import config
|
from trio_typing import TaskStatus
|
||||||
from piker.log import get_logger
|
from fuzzywuzzy import process as fuzzy
|
||||||
|
import numpy as np
|
||||||
from tractor.trionics import (
|
from tractor.trionics import (
|
||||||
broadcast_receiver,
|
broadcast_receiver,
|
||||||
BroadcastReceiver,
|
|
||||||
maybe_open_context
|
maybe_open_context
|
||||||
)
|
)
|
||||||
from tractor import to_asyncio
|
from tractor import to_asyncio
|
||||||
|
# XXX WOOPS XD
|
||||||
|
# yeah you'll need to install it since it was removed in #489 by
|
||||||
|
# accident; well i thought we had removed all usage..
|
||||||
from cryptofeed import FeedHandler
|
from cryptofeed import FeedHandler
|
||||||
|
|
||||||
from cryptofeed.defines import (
|
from cryptofeed.defines import (
|
||||||
DERIBIT,
|
DERIBIT,
|
||||||
L1_BOOK, TRADES,
|
L1_BOOK, TRADES,
|
||||||
|
@ -62,6 +52,17 @@ from cryptofeed.defines import (
|
||||||
)
|
)
|
||||||
from cryptofeed.symbols import Symbol
|
from cryptofeed.symbols import Symbol
|
||||||
|
|
||||||
|
from piker.data.types import Struct
|
||||||
|
from piker.data import def_iohlcv_fields
|
||||||
|
from piker.data._web_bs import (
|
||||||
|
open_jsonrpc_session
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
from piker import config
|
||||||
|
from piker.log import get_logger
|
||||||
|
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,19 +76,6 @@ _ws_url = 'wss://www.deribit.com/ws/api/v2'
|
||||||
_testnet_ws_url = 'wss://test.deribit.com/ws/api/v2'
|
_testnet_ws_url = 'wss://test.deribit.com/ws/api/v2'
|
||||||
|
|
||||||
|
|
||||||
# Broker specific ohlc schema (rest)
|
|
||||||
_ohlc_dtype = [
|
|
||||||
('index', int),
|
|
||||||
('time', int),
|
|
||||||
('open', float),
|
|
||||||
('high', float),
|
|
||||||
('low', float),
|
|
||||||
('close', float),
|
|
||||||
('volume', float),
|
|
||||||
('bar_wap', float), # will be zeroed by sampler if not filled
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class JSONRPCResult(Struct):
|
class JSONRPCResult(Struct):
|
||||||
jsonrpc: str = '2.0'
|
jsonrpc: str = '2.0'
|
||||||
id: int
|
id: int
|
||||||
|
@ -405,7 +393,7 @@ class Client:
|
||||||
|
|
||||||
new_bars.append((i,) + tuple(row))
|
new_bars.append((i,) + tuple(row))
|
||||||
|
|
||||||
array = np.array(new_bars, dtype=_ohlc_dtype) if as_np else klines
|
array = np.array(new_bars, dtype=def_iohlcv_fields) if as_np else klines
|
||||||
return array
|
return array
|
||||||
|
|
||||||
async def last_trades(
|
async def last_trades(
|
||||||
|
|
|
@ -39,7 +39,6 @@ from piker.brokers._util import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from cryptofeed import FeedHandler
|
from cryptofeed import FeedHandler
|
||||||
|
|
||||||
from cryptofeed.defines import (
|
from cryptofeed.defines import (
|
||||||
DERIBIT, L1_BOOK, TRADES, OPTION, CALL, PUT
|
DERIBIT, L1_BOOK, TRADES, OPTION, CALL, PUT
|
||||||
)
|
)
|
||||||
|
|
|
@ -73,12 +73,34 @@ from ib_insync.wrapper import (
|
||||||
from ib_insync.client import Client as ib_Client
|
from ib_insync.client import Client as ib_Client
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
# TODO: in hindsight, probably all imports should be
|
||||||
|
# non-relative for backends so that non-builting backends
|
||||||
|
# can be easily modelled after this style B)
|
||||||
from piker import config
|
from piker import config
|
||||||
from piker.brokers._util import (
|
from piker.brokers._util import (
|
||||||
log,
|
log,
|
||||||
get_logger,
|
get_logger,
|
||||||
)
|
)
|
||||||
from piker.data._source import base_ohlc_dtype
|
|
||||||
|
# Broker specific ohlc schema which includes a vwap field
|
||||||
|
_ohlc_dtype: list[tuple[str, type]] = [
|
||||||
|
('index', int),
|
||||||
|
|
||||||
|
# NOTE XXX: only part that's diff
|
||||||
|
# from our default fields where
|
||||||
|
# time is normally an int.
|
||||||
|
# TODO: can we just cast to this
|
||||||
|
# at np.ndarray load time?
|
||||||
|
('time', float),
|
||||||
|
|
||||||
|
('open', float),
|
||||||
|
('high', float),
|
||||||
|
('low', float),
|
||||||
|
('close', float),
|
||||||
|
('volume', float),
|
||||||
|
('count', int),
|
||||||
|
('bar_wap', float), # Wait do we need this?
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
_time_units = {
|
_time_units = {
|
||||||
|
@ -295,7 +317,7 @@ def bars_to_np(bars: list) -> np.ndarray:
|
||||||
|
|
||||||
nparr = np.array(
|
nparr = np.array(
|
||||||
np_ready,
|
np_ready,
|
||||||
dtype=base_ohlc_dtype,
|
dtype=_ohlc_dtype,
|
||||||
)
|
)
|
||||||
assert nparr['time'][0] == bars[0].date.timestamp()
|
assert nparr['time'][0] == bars[0].date.timestamp()
|
||||||
assert nparr['time'][-1] == bars[-1].date.timestamp()
|
assert nparr['time'][-1] == bars[-1].date.timestamp()
|
||||||
|
|
|
@ -25,11 +25,6 @@ Sub-modules within break into the core functionalities:
|
||||||
wrapping around ``ib_insync``.
|
wrapping around ``ib_insync``.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from piker.log import get_logger
|
|
||||||
|
|
||||||
log = get_logger(__name__)
|
|
||||||
|
|
||||||
from .api import (
|
from .api import (
|
||||||
get_client,
|
get_client,
|
||||||
)
|
)
|
||||||
|
@ -44,8 +39,10 @@ from .broker import (
|
||||||
norm_trade_records,
|
norm_trade_records,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'get_client',
|
'get_client',
|
||||||
|
'get_mkt_info',
|
||||||
'trades_dialogue',
|
'trades_dialogue',
|
||||||
'open_history_client',
|
'open_history_client',
|
||||||
'open_symbol_search',
|
'open_symbol_search',
|
||||||
|
|
|
@ -41,6 +41,7 @@ import trio
|
||||||
|
|
||||||
from piker import config
|
from piker import config
|
||||||
from piker.data.types import Struct
|
from piker.data.types import Struct
|
||||||
|
from piker.data import def_iohlcv_fields
|
||||||
from piker.accounting._mktinfo import (
|
from piker.accounting._mktinfo import (
|
||||||
Asset,
|
Asset,
|
||||||
digits_to_dec,
|
digits_to_dec,
|
||||||
|
@ -52,29 +53,15 @@ from piker.brokers._util import (
|
||||||
DataThrottle,
|
DataThrottle,
|
||||||
)
|
)
|
||||||
from piker.accounting import Transaction
|
from piker.accounting import Transaction
|
||||||
from . import log
|
from piker.log import get_logger
|
||||||
|
|
||||||
|
log = get_logger('piker.brokers.kraken')
|
||||||
|
|
||||||
# <uri>/<version>/
|
# <uri>/<version>/
|
||||||
_url = 'https://api.kraken.com/0'
|
_url = 'https://api.kraken.com/0'
|
||||||
|
# TODO: this is the only backend providing this right?
|
||||||
|
# in which case we should drop it from the defaults and
|
||||||
# Broker specific ohlc schema which includes a vwap field
|
# instead make a custom fields descr in this module!
|
||||||
_ohlc_dtype = [
|
|
||||||
('index', int),
|
|
||||||
('time', int),
|
|
||||||
('open', float),
|
|
||||||
('high', float),
|
|
||||||
('low', float),
|
|
||||||
('close', float),
|
|
||||||
('volume', float),
|
|
||||||
('count', int),
|
|
||||||
('bar_wap', float),
|
|
||||||
]
|
|
||||||
|
|
||||||
# UI components allow this to be declared such that additional
|
|
||||||
# (historical) fields can be exposed.
|
|
||||||
ohlc_dtype = np.dtype(_ohlc_dtype)
|
|
||||||
|
|
||||||
_show_wap_in_history = True
|
_show_wap_in_history = True
|
||||||
_symbol_info_translation: dict[str, str] = {
|
_symbol_info_translation: dict[str, str] = {
|
||||||
'tick_decimals': 'pair_decimals',
|
'tick_decimals': 'pair_decimals',
|
||||||
|
@ -622,11 +609,11 @@ class Client:
|
||||||
new_bars.append(
|
new_bars.append(
|
||||||
(i,) + tuple(
|
(i,) + tuple(
|
||||||
ftype(bar[j]) for j, (name, ftype) in enumerate(
|
ftype(bar[j]) for j, (name, ftype) in enumerate(
|
||||||
_ohlc_dtype[1:]
|
def_iohlcv_fields[1:]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
array = np.array(new_bars, dtype=_ohlc_dtype) if as_np else bars
|
array = np.array(new_bars, dtype=def_iohlcv_fields) if as_np else bars
|
||||||
return array
|
return array
|
||||||
except KeyError:
|
except KeyError:
|
||||||
errmsg = json['error'][0]
|
errmsg = json['error'][0]
|
||||||
|
|
|
@ -63,8 +63,8 @@ from piker.clearing._messages import (
|
||||||
BrokerdPosition,
|
BrokerdPosition,
|
||||||
BrokerdStatus,
|
BrokerdStatus,
|
||||||
)
|
)
|
||||||
from . import log
|
|
||||||
from .api import (
|
from .api import (
|
||||||
|
log,
|
||||||
Client,
|
Client,
|
||||||
BrokerError,
|
BrokerError,
|
||||||
get_client,
|
get_client,
|
||||||
|
|
|
@ -54,8 +54,8 @@ from piker.brokers._util import (
|
||||||
from piker.data.types import Struct
|
from piker.data.types import Struct
|
||||||
from piker.data.validate import FeedInit
|
from piker.data.validate import FeedInit
|
||||||
from piker.data._web_bs import open_autorecon_ws, NoBsWs
|
from piker.data._web_bs import open_autorecon_ws, NoBsWs
|
||||||
from . import log
|
|
||||||
from .api import (
|
from .api import (
|
||||||
|
log,
|
||||||
Client,
|
Client,
|
||||||
Pair,
|
Pair,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue