def testDataAddsUp(self, accounts: List[AccountData]) -> None: aggregator = AccountAggregator(accounts, lenient=False) instruments = set((p.instrument for p in aggregator.positions())) balance = AccountBalance(cash={}) for account in accounts: balance += account.balance() for p in account.positions(): self.assertIn( p.instrument, instruments, msg= f"Expected {p} from {account} to show up in aggregated data", ) for a in account.activity(): self.assertIn( a, aggregator.activity(), msg= f"Expected {a} from {account} to show up in aggregated data", ) self.assertEqual(aggregator.balance(), balance)
def printPositions(accounts: AccountAggregator, args: Namespace) -> None: values: Dict[Position, Cash] = {} if args.live_value: dataProvider = marketDataProvider(accounts) if dataProvider: values = analysis.liveValuesForPositions( accounts.positions(), dataProvider=dataProvider, progressBar=Bar("Loading market data for positions"), ) else: logging.error( "Live data connection required to fetch market values") for p in sorted(accounts.positions(), key=lambda p: p.instrument): print(p) if p in values: print(f"\tMarket value: {values[p]}") elif args.live_value: logging.warning(f"Could not fetch market value for {p.instrument}") print(f"\tCost basis: {p.costBasis}") if args.realized_basis and isinstance(p.instrument, Stock): realizedBasis = analysis.realizedBasisForSymbol( p.instrument.symbol, activity=accounts.activity()) print(f"\tRealized basis: {realizedBasis}")
def printActivity(accounts: AccountAggregator, args: Namespace) -> None: if args.output_csv: df = converter.dataframeForModelObjects(list( accounts.activity())).sort_values(by=["Date"]) df.to_csv(args.output_csv, index=False) print(f"Activity saved to: {args.output_csv}") else: for t in sorted(accounts.activity(), key=lambda t: t.date, reverse=True): print(t)
def main() -> None: args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.INFO) config = loadConfig( chain(Configuration.defaultSearchPaths, args.config if args.config else [])) if not args.command: parser.print_usage() quit(1) mergedSettings: Dict[Settings, str] = dict( chain( readFidelitySettings(config, args).items() if fidelity else [], readSchwabSettings(config, args).items() if schwab else [], readVanguardSettings(config, args).items() if vanguard else [], readIBSettings(config, args).items() if ibkr else [], )) accounts = AccountAggregator.fromSettings(mergedSettings, lenient=args.lenient) commands[args.command](accounts, args)
def symbolTimeline(accounts: AccountAggregator, args: Namespace) -> None: for entry in reversed( list(analysis.timelineForSymbol(args.symbol, accounts.activity()))): print(entry)
def printBalances(accounts: AccountAggregator, args: Namespace) -> None: print(accounts.balance())
def testDiscoversRecursiveDescendants(self) -> None: aggregator = AccountAggregator.fromSettings({}, lenient=False) accountClasses = [type(acct) for acct in aggregator.accounts] self.assertIn(StubRecursiveAccount, accountClasses) self.assertNotIn(RecursiveAccountData, accountClasses)