Skip to content

Commit 989f661

Browse files
committed
cleanup portfolio and position DTOs
1 parent b016b63 commit 989f661

File tree

6 files changed

+46
-86
lines changed

6 files changed

+46
-86
lines changed

HISTORY.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
33
History
44
-------
5+
0.8.119 [2023-06-21]
6+
* cleanup: portfolio and position DTOs
7+
58
0.8.118 [2023-06-19]
69
* feat: enable ledger for polygon
710

credmark/cmf/engine/dev_models/compose_models.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020

2121
class LedgerModelSlugs:
2222

23-
ledger_block_number_time_series = 'ledger.block-number-time-series'
23+
ledger_block_time_series = 'ledger.block-time-series'
24+
ledger_block_number_series = 'ledger.block-number-series'
2425
"""
2526
Get a range of block numbers by end time, interval, and count
2627
"""
@@ -47,7 +48,7 @@ def run_with_local(self, input: MapBlockTimeSeriesInput,
4748
exclusive=input.exclusive
4849
)
4950

50-
block_series = context.run_model(LedgerModelSlugs.ledger_block_number_time_series,
51+
block_series = context.run_model(LedgerModelSlugs.ledger_block_time_series,
5152
ts_input,
5253
return_type=LedgerBlockNumberTimeSeries)
5354

@@ -93,9 +94,11 @@ class ComposeMapBlockTimeSeriesModel(ComposeMapBlockTimeSeriesModelMeta):
9394
def run(self, input: MapBlockTimeSeriesInput) -> MapBlockTimeSeriesOutput[dict]:
9495
return self.run_with_local(input, local=False)
9596

97+
9698
class MapBlockTimeSeriesInputLocal(MapBlockTimeSeriesInput):
9799
class Config:
98-
schema_extra = MapBlockTimeSeriesInput.Config.schema_extra | {'skip_test': True}
100+
schema_extra = MapBlockTimeSeriesInput.Config.schema_extra | {
101+
'skip_test': True}
99102

100103

101104
@Model.describe(slug='compose.map-block-time-series-local',

credmark/cmf/engine/dev_models/console.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,16 @@
3737
FiatCurrency,
3838
JoinType,
3939
Maybe,
40-
NativePosition,
4140
NativeToken,
4241
Network,
4342
Portfolio,
44-
PortfolioWithPrice,
4543
Position,
46-
PositionWithPrice,
4744
Price,
4845
PriceList,
4946
PriceWithQuote,
5047
Records,
5148
Some,
5249
Token,
53-
TokenPosition,
5450
Tokens,
5551
)
5652
from credmark.cmf.types.compose import (

credmark/cmf/types/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
from .ledger_query import LedgerQuery
2323
from .ledger_series import LedgerBlockNumberTimeSeries, LedgerBlockTimeSeriesInput
2424
from .network import Network, NetworkDict
25-
from .portfolio import Portfolio, PortfolioWithPrice
26-
from .position import NativePosition, NativePositionWithPrice, Position, PositionWithPrice, TokenPosition
25+
from .portfolio import Portfolio
26+
from .position import Position
2727
from .price import Price, PriceList, PriceWithQuote
2828
from .token_erc20 import NativeToken, Token, Tokens
2929
from .token_wei import TokenWei

credmark/cmf/types/portfolio.py

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,53 @@
1+
import math
12
from typing import List
23

4+
import credmark.cmf.model
35
from credmark.dto import DTOField, IterableListGenericDTO, PrivateAttr
46

5-
from .position import Position, PositionWithPrice
7+
from .adt import Maybe, Some
8+
from .position import Position
9+
from .price import PriceWithQuote
610

711

812
class Portfolio(IterableListGenericDTO[Position]):
913
positions: List[Position] = DTOField(
1014
default=[], description='List of positions')
1115
_iterator: str = PrivateAttr('positions')
1216

13-
def get_value(self, price_model='price.quote', block_number=None, quote=None):
17+
def get_value(self, block_number=None, quote=None):
1418
"""
1519
Returns:
1620
The value of the portfolio using the price_model.
1721
1822
Raises:
1923
ModelDataError: if no pools available for a position's price data.
2024
"""
21-
if len(self.positions) > 0:
22-
total = 0
23-
for pos in self.positions:
24-
total += pos.get_value(price_model, block_number=block_number, quote=quote)
25-
return total
26-
return 0
25+
non_zero_positions = [position for position in self.positions
26+
if not math.isclose(position.amount, 0)]
27+
28+
if len(non_zero_positions) == 0:
29+
return 0
30+
31+
total = 0
32+
context = credmark.cmf.model.ModelContext.current_context()
33+
if block_number is None:
34+
block_number = context.block_number
35+
36+
pqs_maybe = context.run_model(
37+
slug='price.quote-multiple-maybe',
38+
input=Some(some=[
39+
{'base': p.asset.address} if quote is None
40+
else {'base': p.asset.address, 'quote': quote}
41+
for p in non_zero_positions
42+
]),
43+
block_number=block_number,
44+
return_type=Some[Maybe[PriceWithQuote]],
45+
)
46+
for price_maybe, position in zip(pqs_maybe.some, non_zero_positions):
47+
if price_maybe.just is not None:
48+
total += position.amount * price_maybe.just.price
49+
50+
return total
2751

2852
class Config:
2953
schema_extra: dict = {
@@ -48,47 +72,3 @@ def merge(cls, port1: "Portfolio", port2: "Portfolio"):
4872
positions[pos_key].amount += pos.amount
4973

5074
return cls(positions=list(positions.values()))
51-
52-
53-
class PortfolioWithPrice(IterableListGenericDTO[PositionWithPrice]):
54-
positions: List[PositionWithPrice] = DTOField(
55-
default=[], description='List of positions')
56-
_iterator: str = PrivateAttr('positions')
57-
58-
def get_value(self, price_model='price.quote', block_number=None, quote=None):
59-
"""
60-
Returns:
61-
The value of the portfolio using the price_model.
62-
63-
Raises:
64-
ModelDataError: if no pools available for a position's price data.
65-
"""
66-
if len(self.positions) > 0:
67-
return sum(pos.get_value(price_model, block_number=block_number, quote=quote)
68-
for pos in self.positions) # pylint:disable=not-an-iterable
69-
return 0
70-
71-
class Config:
72-
schema_extra: dict = {
73-
'examples': [{'positions': [exp]}
74-
for exp in PositionWithPrice.Config.schema_extra['examples']]
75-
}
76-
77-
@classmethod
78-
def merge(cls, port1: "Portfolio", port2: "Portfolio"):
79-
positions = {}
80-
for pos in port1:
81-
pos_key = str(pos.asset.address)
82-
if positions.get(pos_key, None) is None:
83-
positions[pos_key] = pos.copy()
84-
else:
85-
positions[pos_key].amount += pos.amount
86-
87-
for pos in port2:
88-
pos_key = str(pos.asset.address)
89-
if positions.get(pos_key, None) is None:
90-
positions[pos_key] = pos.copy()
91-
else:
92-
positions[pos_key].amount += pos.amount
93-
94-
return cls(positions=list(positions.values()))

credmark/cmf/types/position.py

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
from credmark.dto import DTO, DTOField, cross_examples
66

77
from .price import PriceWithQuote
8-
from .token_erc20 import NativeToken, Token
8+
from .token_erc20 import Token
99

1010

1111
class Position(DTO):
1212
amount: float = DTOField(0.0, description='Quantity of token held')
1313
asset: Token
14+
price_quote: Optional[PriceWithQuote] = None
1415

1516
def get_value(self, price_model='price.quote', block_number=None, quote=None) -> float:
1617
"""
@@ -39,31 +40,8 @@ def get_value(self, price_model='price.quote', block_number=None, quote=None) ->
3940

4041
class Config:
4142
schema_extra = {
42-
'examples': cross_examples([{'amount': '4.2', }],
43+
'examples': cross_examples([{'amount': '4.2'}],
4344
[{'token': v}
4445
for v in Token.Config.schema_extra['examples']],
4546
limit=10)
4647
}
47-
48-
49-
class TokenPosition(Position):
50-
asset: Token
51-
52-
53-
class NativePosition(Position):
54-
asset: NativeToken
55-
56-
57-
class NativePositionWithPrice(NativePosition):
58-
fiat_quote: Optional[PriceWithQuote]
59-
60-
61-
class PositionWithPrice(Position):
62-
fiat_quote: Optional[PriceWithQuote]
63-
64-
class Config:
65-
schema_extra = {
66-
'examples': cross_examples(Position.Config.schema_extra['examples'],
67-
PriceWithQuote.Config.schema_extra['examples'],
68-
limit=10)
69-
}

0 commit comments

Comments
 (0)