Coverage for hledger_lots/fifo_info.py: 63%
70 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-05-05 00:05 -0300
« prev ^ index » next coverage.py v7.2.3, created at 2023-05-05 00:05 -0300
1from datetime import datetime
2from typing import Optional, Tuple
4from .checks import MultipleBaseCurrencies
5from .fifo import get_lots
6from .hl import hledger2txn
7from .info import AllInfo, Info, LotsInfo
8from .lib import dt_list2table, get_avg_fifo
11class FifoInfo(Info):
12 def __init__(
13 self,
14 journals: Tuple[str, ...],
15 commodity: str,
16 check: bool,
17 no_desc: Optional[str] = None,
18 ):
19 super().__init__(journals, commodity,no_desc)
20 self.check = check
22 self.lots = get_lots(self.txns, check)
23 self.last_buy_date = self.lots[-1].date if len(self.lots) > 0 else None
25 self.buy_lots = get_lots(self.txns, check)
26 self.table = dt_list2table(self.buy_lots)
28 def get_info(self):
29 if len(self.txns) == 0:
30 return None
32 commodity = self.commodity
34 cur = self.lots[0].base_cur
35 qtty = sum(lot.qtty for lot in self.lots)
36 amount = sum(lot.price * lot.qtty for lot in self.lots)
37 avg_cost = get_avg_fifo(self.lots) if qtty > 0 else 0
39 if self.has_txn:
40 last_buy_date_str = self.lots[-1].date
41 last_buy_date = datetime.strptime(last_buy_date_str, "%Y-%m-%d").date()
42 xirr = self.get_lots_xirr(last_buy_date)
43 else:
44 xirr = 0
46 if self.market_price and self.market_date and xirr:
47 market_price_str = f"{self.market_price:,.4f}"
48 market_amount = self.market_price * qtty
49 market_amount_str = f"{market_amount:,.2f}"
50 market_profit = market_amount - amount
51 market_profit_str = f"{market_profit:,.2f}"
52 market_date = self.market_date.strftime("%Y-%m-%d")
54 xirr_str = f"{xirr:,.4f}%"
55 else:
56 market_amount_str = ""
57 market_profit_str = ""
58 market_date = ""
59 market_price_str = ""
60 xirr_str = ""
62 return LotsInfo(
63 comm=commodity,
64 cur=cur,
65 qtty=str(qtty),
66 amount=f"{amount:,.2f}",
67 avg_cost=f"{avg_cost:,.4f}",
68 mkt_price=market_price_str,
69 mkt_amount=market_amount_str,
70 mkt_profit=market_profit_str,
71 mkt_date=market_date,
72 xirr=xirr_str,
73 )
75 @property
76 def info_txt(self):
77 info = self.get_info()
78 if not info:
79 return f"No transactions available for {self.commodity}"
80 return self.get_info_txt(info)
83class AllFifoInfo(AllInfo):
84 def __init__(self, journals: Tuple[str, ...], no_desc: str, check: bool):
85 super().__init__(journals, no_desc)
86 self.check = check
88 def get_info(self, commodity: str):
89 txns = hledger2txn(self.journals, commodity, self.no_desc)
90 try:
91 lots = get_lots(txns, self.check)
92 except MultipleBaseCurrencies:
93 return None
95 if len(lots) > 0:
96 lot_info = FifoInfo(self.journals, commodity, self.check).get_info()
97 return lot_info
99 @property
100 def infos(self):
101 infos = [self.get_info(com) for com in self.commodities]
102 infos = [info for info in infos if info is not None]
103 return infos
105 def infos_table(self, output_format: str):
106 return self.get_infos_table(self.infos, output_format)
108 def infos_csv(self):
109 return self.get_infos_csv(self.infos)