This repository has been archived by the owner on Jan 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aggregator.py
71 lines (60 loc) · 2.21 KB
/
aggregator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import operator
from functools import reduce
from itertools import chain, groupby
from typing import Dict, Iterable, Mapping, Optional, Sequence
from bankroll.model import AccountBalance, Activity, Position
from .account import AccountData
from .configuration import Configuration, Settings
class AccountAggregator(AccountData):
@classmethod
def allSettings(cls, config: Configuration) -> Dict[Settings, str]:
return dict(
chain.from_iterable(
(
config.section(settingsCls).items()
for settingsCls in Settings.__subclasses__()
)
)
)
@classmethod
def fromSettings(
cls, settings: Mapping[Settings, str], lenient: bool
) -> "AccountAggregator":
return AccountAggregator(
accounts=(
accountCls.fromSettings(settings, lenient=lenient)
for accountCls in AccountData.__subclasses__()
if not issubclass(accountCls, AccountAggregator)
),
lenient=lenient,
)
def __init__(self, accounts: Iterable[AccountData], lenient: bool):
self._accounts = list(accounts)
self._lenient = lenient
super().__init__()
def _deduplicatePositions(
self, positions: Iterable[Position]
) -> Iterable[Position]:
return (
reduce(operator.add, ps)
for i, ps in groupby(
sorted(positions, key=lambda p: p.instrument),
key=lambda p: p.instrument,
)
)
def positions(self) -> Iterable[Position]:
# TODO: Memoize the result of deduplication?
return self._deduplicatePositions(
chain.from_iterable((account.positions() for account in self._accounts))
)
def activity(self) -> Iterable[Activity]:
return chain.from_iterable((account.activity() for account in self._accounts))
def balance(self) -> AccountBalance:
return reduce(
operator.add,
(account.balance() for account in self._accounts),
AccountBalance(cash={}),
)
@property
def accounts(self) -> Sequence[AccountData]:
return self._accounts