Skip to content

Commit e51ba40

Browse files
authored
Merge pull request #489 from pikers/rekt_pps
Rekt pps? problem? => `piker.accounting`
2 parents 073ff01 + abd3cef commit e51ba40

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+7652
-4311
lines changed

.github/workflows/ci.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,21 @@ jobs:
4343
- name: Checkout
4444
uses: actions/checkout@v3
4545

46-
- name: Build DB container
47-
run: docker build -t piker:elastic dockering/elastic
46+
# elastic only
47+
# - name: Build DB container
48+
# run: docker build -t piker:elastic dockering/elastic
4849

4950
- name: Setup python
50-
uses: actions/setup-python@v3
51+
uses: actions/setup-python@v4
5152
with:
5253
python-version: '3.10'
5354

55+
# elastic only
56+
# - name: Install dependencies
57+
# run: pip install -U .[es] -r requirements-test.txt -r requirements.txt --upgrade-strategy eager
58+
5459
- name: Install dependencies
55-
run: pip install -U .[es] -r requirements-test.txt -r requirements.txt --upgrade-strategy eager
60+
run: pip install -U . -r requirements-test.txt -r requirements.txt --upgrade-strategy eager
5661

5762
- name: Test suite
5863
run: pytest tests -rs

config/brokers.toml

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
[questrade]
2-
refresh_token = ""
3-
access_token = ""
4-
api_server = "https://api06.iq.questrade.com/"
2+
refresh_token = ''
3+
access_token = ''
4+
api_server = 'https://api06.iq.questrade.com/'
55
expires_in = 1800
6-
token_type = "Bearer"
6+
token_type = 'Bearer'
77
expires_at = 1616095326.355846
88

9+
10+
[deribit]
11+
key_id = ''
12+
key_secret = ''
13+
14+
915
[kraken]
10-
key_descr = "api_0"
11-
api_key = ""
12-
secret = ""
16+
key_descr = ''
17+
api_key = ''
18+
secret = ''
19+
20+
21+
[kucoin]
22+
key_id = ''
23+
key_secret = ''
24+
key_passphrase = ''
25+
1326

1427
[ib]
1528
hosts = [
16-
"127.0.0.1",
29+
'127.0.0.1',
1730
]
1831
# XXX: the order in which ports will be scanned
1932
# (by the `brokerd` daemon-actor)
@@ -30,8 +43,8 @@ ports = [
3043
# is not supported so you have to manually download
3144
# and XML report and put it in a location that can be
3245
# accessed by the ``brokerd.ib`` backend code for parsing.
33-
flex_token = '666666666666666666666666'
34-
flex_trades_query_id = '666666' # live account
46+
flex_token = ''
47+
flex_trades_query_id = '' # live account
3548

3649
# when clients are being scanned this determines
3750
# which clients are preferred to be used for data
@@ -47,11 +60,6 @@ prefer_data_account = [
4760
# the order in which accounts will be selectable
4861
# in the order mode UI (if found via clients during
4962
# API-app scanning)when a new symbol is loaded.
50-
paper = "XX0000000"
51-
margin = "X0000000"
52-
ira = "X0000000"
53-
54-
55-
[deribit]
56-
key_id = 'XXXXXXXX'
57-
key_secret = 'Xx_XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx'
63+
paper = 'XX0000000'
64+
margin = 'X0000000'
65+
ira = 'X0000000'

config/conf.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[network]
2+
tsdb.backend = 'marketstore'
3+
tsdb.host = 'localhost'
4+
tsdb.grpc_port = 5995

dockering/ib/docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,21 @@
22
# https://github.com/waytrade/ib-gateway-docker/blob/master/docker-compose.yml
33
version: "3.5"
44

5+
56
services:
7+
68
ib_gw_paper:
9+
10+
# apparently java is a mega cukc:
11+
# https://stackoverflow.com/a/56895801
12+
# https://bugs.openjdk.org/browse/JDK-8150460
13+
ulimits:
14+
# nproc: 65535
15+
nproc: 6000
16+
nofile:
17+
soft: 2000
18+
hard: 3000
19+
720
# other image tags available:
821
# https://github.com/waytrade/ib-gateway-docker#supported-tags
922
# image: waytrade/ib-gateway:981.3j

piker/_cacheables.py

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# piker: trading gear for hackers
2-
# Copyright (C) Tyler Goodlet (in stewardship for piker0)
2+
# Copyright (C) Tyler Goodlet (in stewardship for pikers)
33

44
# This program is free software: you can redistribute it and/or modify
55
# it under the terms of the GNU Affero General Public License as published by
@@ -14,14 +14,20 @@
1414
# You should have received a copy of the GNU Affero General Public License
1515
# along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

17-
"""
17+
'''
1818
Cacheing apis and toolz.
1919
20-
"""
20+
'''
2121

2222
from collections import OrderedDict
2323
from contextlib import (
24-
asynccontextmanager,
24+
asynccontextmanager as acm,
25+
)
26+
from typing import (
27+
Awaitable,
28+
Callable,
29+
ParamSpec,
30+
TypeVar,
2531
)
2632

2733
from tractor.trionics import maybe_open_context
@@ -32,19 +38,54 @@
3238

3339
log = get_logger(__name__)
3440

35-
36-
def async_lifo_cache(maxsize=128):
37-
"""Async ``cache`` with a LIFO policy.
41+
T = TypeVar("T")
42+
P = ParamSpec("P")
43+
44+
45+
# TODO: move this to `tractor.trionics`..
46+
# - egs. to replicate for tests: https://github.com/aio-libs/async-lru#usage
47+
# - their suite as well:
48+
# https://github.com/aio-libs/async-lru/tree/master/tests
49+
# - asked trio_util about it too:
50+
# https://github.com/groove-x/trio-util/issues/21
51+
def async_lifo_cache(
52+
maxsize=128,
53+
54+
# NOTE: typing style was learned from:
55+
# https://stackoverflow.com/a/71132186
56+
) -> Callable[
57+
Callable[P, Awaitable[T]],
58+
Callable[
59+
Callable[P, Awaitable[T]],
60+
Callable[P, Awaitable[T]],
61+
],
62+
]:
63+
'''
64+
Async ``cache`` with a LIFO policy.
3865
3966
Implemented my own since no one else seems to have
4067
a standard. I'll wait for the smarter people to come
4168
up with one, but until then...
42-
"""
69+
70+
NOTE: when decorating, due to this simple/naive implementation, you
71+
MUST call the decorator like,
72+
73+
.. code:: python
74+
75+
@async_lifo_cache()
76+
async def cache_target():
77+
78+
'''
4379
cache = OrderedDict()
4480

45-
def decorator(fn):
81+
def decorator(
82+
fn: Callable[P, Awaitable[T]],
83+
) -> Callable[P, Awaitable[T]]:
4684

47-
async def wrapper(*args):
85+
async def decorated(
86+
*args: P.args,
87+
**kwargs: P.kwargs,
88+
) -> T:
4889
key = args
4990
try:
5091
return cache[key]
@@ -53,16 +94,20 @@ async def wrapper(*args):
5394
# discard last added new entry
5495
cache.popitem()
5596

56-
# do it
57-
cache[key] = await fn(*args)
97+
# call underlying
98+
cache[key] = await fn(
99+
*args,
100+
**kwargs,
101+
)
58102
return cache[key]
59103

60-
return wrapper
104+
return decorated
61105

62106
return decorator
63107

64108

65-
@asynccontextmanager
109+
# TODO: move this to `.brokers.utils`..
110+
@acm
66111
async def open_cached_client(
67112
brokername: str,
68113
) -> 'Client': # noqa

piker/accounting/__init__.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# piker: trading gear for hackers
2+
# Copyright (C) Tyler Goodlet (in stewardship for pikers)
3+
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU Affero General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU Affero General Public License for more details.
13+
14+
# You should have received a copy of the GNU Affero General Public License
15+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
'''
18+
"Accounting for degens": count dem numberz that tracks how much you got
19+
for tendiez.
20+
21+
'''
22+
from ..log import get_logger
23+
24+
from ._ledger import (
25+
iter_by_dt,
26+
Transaction,
27+
TransactionLedger,
28+
open_trade_ledger,
29+
)
30+
from ._pos import (
31+
load_pps_from_ledger,
32+
open_pps,
33+
Position,
34+
PpTable,
35+
)
36+
from ._mktinfo import (
37+
Asset,
38+
dec_digits,
39+
digits_to_dec,
40+
MktPair,
41+
Symbol,
42+
unpack_fqme,
43+
)
44+
from ._allocate import (
45+
mk_allocator,
46+
Allocator,
47+
)
48+
49+
log = get_logger(__name__)
50+
51+
__all__ = [
52+
'Allocator',
53+
'Asset',
54+
'MktPair',
55+
'Position',
56+
'PpTable',
57+
'Symbol',
58+
'Transaction',
59+
'TransactionLedger',
60+
'dec_digits',
61+
'digits_to_dec',
62+
'iter_by_dt',
63+
'load_pps_from_ledger',
64+
'mk_allocator',
65+
'open_pps',
66+
'open_trade_ledger',
67+
'unpack_fqme',
68+
]
69+
70+
71+
def get_likely_pair(
72+
src: str,
73+
dst: str,
74+
bs_mktid: str,
75+
76+
) -> str | None:
77+
'''
78+
Attempt to get the likely trading pair matching a given destination
79+
asset `dst: str`.
80+
81+
'''
82+
try:
83+
src_name_start = bs_mktid.rindex(src)
84+
except (
85+
ValueError, # substr not found
86+
):
87+
# TODO: handle nested positions..(i.e.
88+
# positions where the src fiat was used to
89+
# buy some other dst which was furhter used
90+
# to buy another dst..)
91+
# log.warning(
92+
# f'No src fiat {src} found in {bs_mktid}?'
93+
# )
94+
return
95+
96+
likely_dst = bs_mktid[:src_name_start]
97+
if likely_dst == dst:
98+
return bs_mktid
99+
100+
101+
if __name__ == '__main__':
102+
import sys
103+
from pprint import pformat
104+
105+
args = sys.argv
106+
assert len(args) > 1, 'Specifiy account(s) from `brokers.toml`'
107+
args = args[1:]
108+
for acctid in args:
109+
broker, name = acctid.split('.')
110+
trans, updated_pps = load_pps_from_ledger(broker, name)
111+
print(
112+
f'Processing transactions into pps for {broker}:{acctid}\n'
113+
f'{pformat(trans)}\n\n'
114+
f'{pformat(updated_pps)}'
115+
)

0 commit comments

Comments
 (0)