Don't override `Account.pps: dict` entries..
Despite a `.bs_mktid` ideally being a bijection with `MktPair.fqme` values, apparently some backends (cough IB) will switch the .<venue>` part in txn records resulting in multiple account-conf-file sections for the same dst asset. Obviously that means we can't allocate new `Position` entries keyed by that `bs_mktid`, instead be sure to **update them instead**! Deats, - add case logic to avoid pp overwrites using a `pp_objs.get()` check. - warn on duplicated pos entries whenever the current account-file entry's `mkt` doesn't match the pre-existing position's. - mk `Position.add_clear()` return a `bool` indicating if the record was newly added, warn when it was already existing/added prior. Also, - drop the already deprecated `open_pps()`, also from sub-pkg exports. - draft TODO for `Position.summary()` idea as a replacement for `BrokerdPosition`-msgs.qt_w_graceful_SIGINT
							parent
							
								
									6cc3518143
								
							
						
					
					
						commit
						b0f273f091
					
				|  | @ -33,7 +33,6 @@ from ._pos import ( | |||
|     Account, | ||||
|     load_account, | ||||
|     load_account_from_ledger, | ||||
|     open_pps, | ||||
|     open_account, | ||||
|     Position, | ||||
| ) | ||||
|  | @ -68,7 +67,6 @@ __all__ = [ | |||
|     'load_account_from_ledger', | ||||
|     'mk_allocator', | ||||
|     'open_account', | ||||
|     'open_pps', | ||||
|     'open_trade_ledger', | ||||
|     'unpack_fqme', | ||||
|     'DerivTypes', | ||||
|  |  | |||
|  | @ -353,13 +353,12 @@ class Position(Struct): | |||
|     ) -> bool: | ||||
|         ''' | ||||
|         Update clearing table by calculating the rolling ppu and | ||||
|         (accumulative) size in both the clears entry and local | ||||
|         attrs state. | ||||
|         (accumulative) size in both the clears entry and local attrs | ||||
|         state. | ||||
| 
 | ||||
|         Inserts are always done in datetime sorted order. | ||||
| 
 | ||||
|         ''' | ||||
|         # added: bool = False | ||||
|         tid: str = t.tid | ||||
|         if tid in self._events: | ||||
|             log.debug( | ||||
|  | @ -367,7 +366,7 @@ class Position(Struct): | |||
|                 f'\n' | ||||
|                 f'{t}\n' | ||||
|             ) | ||||
|             # return added | ||||
|             return False | ||||
| 
 | ||||
|         # TODO: apparently this IS possible with a dict but not | ||||
|         # common and probably not that beneficial unless we're also | ||||
|  | @ -448,6 +447,12 @@ class Position(Struct): | |||
|     # def suggest_split(self) -> float: | ||||
|     #     ... | ||||
| 
 | ||||
|     # ?TODO, for sending rendered state over the wire? | ||||
|     # def summary(self) -> PositionSummary: | ||||
|         # do minimal conversion to a subset of fields | ||||
|         # currently defined in `.clearing._messages.BrokerdPosition` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class Account(Struct): | ||||
|     ''' | ||||
|  | @ -491,9 +496,9 @@ class Account(Struct): | |||
| 
 | ||||
|     def update_from_ledger( | ||||
|         self, | ||||
|         ledger: TransactionLedger | dict[str, Transaction], | ||||
|         ledger: TransactionLedger|dict[str, Transaction], | ||||
|         cost_scalar: float = 2, | ||||
|         symcache: SymbologyCache | None = None, | ||||
|         symcache: SymbologyCache|None = None, | ||||
| 
 | ||||
|         _mktmap_table: dict[str, MktPair] | None = None, | ||||
| 
 | ||||
|  | @ -714,7 +719,7 @@ class Account(Struct): | |||
|         # XXX WTF: if we use a tomlkit.Integer here we get this | ||||
|         # super weird --1 thing going on for cumsize!?1! | ||||
|         # NOTE: the fix was to always float() the size value loaded | ||||
|         # in open_pps() below! | ||||
|         # in open_account() below! | ||||
|         config.write( | ||||
|             config=self.conf, | ||||
|             path=self.conf_path, | ||||
|  | @ -898,7 +903,6 @@ def open_account( | |||
|             clears_table['dt'] = dt | ||||
|             trans.append(Transaction( | ||||
|                 fqme=bs_mktid, | ||||
|                 # sym=mkt, | ||||
|                 bs_mktid=bs_mktid, | ||||
|                 tid=tid, | ||||
|                 # XXX: not sure why sometimes these are loaded as | ||||
|  | @ -921,11 +925,22 @@ def open_account( | |||
|         ): | ||||
|             expiry: pendulum.DateTime = pendulum.parse(expiry) | ||||
| 
 | ||||
|         pp = pp_objs[bs_mktid] = Position( | ||||
|             mkt, | ||||
|             split_ratio=split_ratio, | ||||
|             bs_mktid=bs_mktid, | ||||
|         ) | ||||
|         # !XXX, should never be duplicates over | ||||
|         # a backend-(broker)-system's unique market-IDs! | ||||
|         if pos := pp_objs.get(bs_mktid): | ||||
|             if mkt != pos.mkt: | ||||
|                 log.warning( | ||||
|                     f'Duplicated position but diff `MktPair.fqme` ??\n' | ||||
|                     f'bs_mktid: {bs_mktid!r}\n' | ||||
|                     f'pos.mkt: {pos.mkt}\n' | ||||
|                     f'mkt: {mkt}\n' | ||||
|                 ) | ||||
|         else: | ||||
|             pos = pp_objs[bs_mktid] = Position( | ||||
|                 mkt, | ||||
|                 split_ratio=split_ratio, | ||||
|                 bs_mktid=bs_mktid, | ||||
|             ) | ||||
| 
 | ||||
|         # XXX: super critical, we need to be sure to include | ||||
|         # all pps.toml clears to avoid reusing clears that were | ||||
|  | @ -933,8 +948,13 @@ def open_account( | |||
|         # state, since today's records may have already been | ||||
|         # processed! | ||||
|         for t in trans: | ||||
|             pp.add_clear(t) | ||||
| 
 | ||||
|             added: bool = pos.add_clear(t) | ||||
|             if not added: | ||||
|                 log.warning( | ||||
|                     f'Txn already recorded in pp ??\n' | ||||
|                     f'\n' | ||||
|                     f'{t}\n' | ||||
|                 ) | ||||
|     try: | ||||
|         yield acnt | ||||
|     finally: | ||||
|  | @ -942,20 +962,6 @@ def open_account( | |||
|             acnt.write_config() | ||||
| 
 | ||||
| 
 | ||||
| # TODO: drop the old name and THIS! | ||||
| @cm | ||||
| def open_pps( | ||||
|     *args, | ||||
|     **kwargs, | ||||
| ) -> Generator[Account, None, None]: | ||||
|     log.warning( | ||||
|         '`open_pps()` is now deprecated!\n' | ||||
|         'Please use `with open_account() as cnt:`' | ||||
|     ) | ||||
|     with open_account(*args, **kwargs) as acnt: | ||||
|         yield acnt | ||||
| 
 | ||||
| 
 | ||||
| def load_account_from_ledger( | ||||
| 
 | ||||
|     brokername: str, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue