def test_value_by_column(self): ldgr = Ledger(Column("Domestic", Cy.GBP, Role.asset, "{} assets"), Column("Domestic", Cy.GBP, Role.capital, "{} capital"), ref=Cy.GBP) assets = next(i for i in ldgr.columns.values() if i.role is Role.asset) ldgr.commit(120, assets) self.assertEqual(120, ldgr.value(assets))
def test_track_exchange_gain_with_fixed_assets(self): """ From Selinger table 4.1 date asset asset capital gain Jan 1 Balance (1 USD = 1.20 CAD) CAD 60 USD 100 CAD 180 CAD 0 Jan 2 Balance (1 USD = 1.30 CAD) CAD 60 USD 100 CAD 180 CAD 10 Jan 3 Balance (1 USD = 1.25 CAD) CAD 60 USD 100 CAD 180 CAD 5 Jan 4 Balance (1 USD = 1.15 CAD) CAD 60 USD 100 CAD 180 – CAD 5 """ ldgr = Ledger(Column("Canadian cash", Cy.CAD, Role.asset, "{}"), Column("US cash", Cy.USD, Role.asset, "{}"), Column("Capital", Cy.CAD, Role.capital, "{}"), ref=Cy.CAD) usC = ldgr.columns["US cash"] for args in ldgr.adjustments(Exchange({(Cy.USD, Cy.CAD): Dl("1.2")})): ldgr.commit(*args, ts=datetime.date(2013, 1, 1), note="1 USD = 1.20 CAD") lhs, rhs, st = ldgr.equation self.assertEqual(lhs, rhs) self.assertIs(st, Status.ok) for deposit, col in zip((Dl(60), Dl(100), Dl(180)), ldgr.columns.values()): ldgr.commit(deposit, col, ts=datetime.date(2013, 1, 1), note="Initial balance") lhs, rhs, st = ldgr.equation self.assertEqual(lhs, rhs) self.assertIs(st, Status.ok) trade, col, exchange = next( ldgr.adjustments(Exchange({(Cy.USD, Cy.CAD): Dl("1.3")}), [usC])) self.assertIs(col, usC) self.assertEqual(10, trade.gain) trade, col, exchange = next( ldgr.adjustments(Exchange({(Cy.USD, Cy.CAD): Dl("1.25")}), [usC])) self.assertIs(col, usC) self.assertEqual(5, trade.gain) trade, col, exchange = next( ldgr.adjustments(Exchange({(Cy.USD, Cy.CAD): Dl("1.15")}), [usC])) self.assertIs(col, usC) self.assertEqual(-5, trade.gain) lhs, rhs, st = ldgr.equation self.assertEqual(lhs, rhs) self.assertIs(st, Status.ok)
def test_output_sequential_journals(self): ldgr = Ledger( Column("Canadian cash", Cy.CAD, Role.asset, "{}"), Column("US cash", Cy.USD, Role.asset, "{}"), Column("Capital", Cy.CAD, Role.capital, "{}"), Column("Expense", Cy.CAD, Role.expense, "{}"), ref=Cy.CAD) cols = ldgr.columns for amount, col in zip( (Dl(200), Dl(0), Dl(200), Dl(0)), ldgr.columns.values() ): ldgr.commit(amount, col) out = io.StringIO() print(metadata(ldgr), file=out) print(journal( ldgr, ts=datetime.date(2013, 1, 1), note="Opening balance"), file=out) exchange = Exchange({(Cy.USD, Cy.CAD): Dl("1.2")}) for args in ldgr.adjustments(exchange): ldgr.commit(*args) print(journal( ldgr, ts=datetime.date(2013, 1, 2), note="1 USD -> 1.20 CAD"), file=out) ldgr.commit(-20, cols["Canadian cash"]) ldgr.commit(20, cols["Expense"]) print(journal( ldgr, ts=datetime.date(2013, 1, 3), note="Buy food"), file=out) objs = rson.loads(out.getvalue()) self.assertEqual(8, len(objs)) self.assertEqual([180., 0., 200., 20., 0., 0.], objs[-1])
def test_output_metadata(self): ldgr = Ledger( Column("Canadian cash", Cy.CAD, Role.asset, "{}"), Column("US cash", Cy.USD, Role.asset, "{}"), Column("Capital", Cy.CAD, Role.capital, "{}"), Column("Expense", Cy.CAD, Role.expense, "{}"), ref=Cy.CAD) m = metadata(ldgr) out = rson.loads(m) self.assertEqual(2, len(out)) self.assertIn("header", out[0]) self.assertEqual( tallywallet.common.__version__, str(out[0]["header"]["version"]) ) self.assertIn("ledger", out[1]) # Two columns are added by ledger for USD and CAD trading self.assertEqual(6, len(out[1]["ledger"]["columns"])) self.assertEqual("CAD", out[1]["ledger"]["ref"])
def test_output_journal(self): ldgr = Ledger( Column("Canadian cash", Cy.CAD, Role.asset, "{}"), Column("US cash", Cy.USD, Role.asset, "{}"), Column("Capital", Cy.CAD, Role.capital, "{}"), Column("Expense", Cy.CAD, Role.expense, "{}"), ref=Cy.CAD) for amount, col in zip( (Dl(200), Dl(0), Dl(200), Dl(0)), ldgr.columns.values() ): (_, _, _, _, st) = ldgr.commit(amount, col) self.assertIs(Status.ok, st) t = journal( ldgr, ts=datetime.date(2013, 1, 1), note="Opening balance") out = rson.loads(t) self.assertEqual(2, len(out)) self.assertEqual( {"ts": "2013-01-01", "note": "Opening balance"}, out[0]) self.assertEqual(6, len(out[1])) self.assertEqual(400, sum(out[1]))
__all__ = [ "HOUR", "DAY", "WEEK", "YEAR", "INITIAL", "banking_licence", "bank_loan", "bank_charge", "nonbank_interest", "firms_repayment", "firms_wages", "nonfirms_consumption", "columns", "simulate" ] SEC = 1 HOUR = 60 * 60 * SEC DAY = 24 * HOUR WEEK = 7 * DAY YEAR = 52 * WEEK INITIAL = int(100E6) columns = OrderedDict((i.ref, i) for i in ( Column("licence", Cy.USD, Role.asset, "{}"), Column("loans", Cy.USD, Role.asset, "{}"), Column("vault", Cy.USD, Role.liability, "{}"), Column("firms", Cy.USD, Role.liability, "{}"), Column("workers", Cy.USD, Role.liability, "{}"), Column("safe", Cy.USD, Role.income, "{}"), )) def banking_licence(ldgr, val): """ Wilson's suggestion is to formalise the ability of a bank to create money. His first step (not present in Keen) is to capture this value as an asset. 1. Grant licence
def test_balance(self): ldgr = Ledger(Column("Domestic", Cy.GBP, Role.asset, "{} assets"), Column("Domestic", Cy.GBP, Role.capital, "{} capital"), ref=Cy.GBP) self.assertEqual(2, len(ldgr.balance("Domestic")))
def test_commit_exchange_gain_via_expenses(self): """ From Selinger table 4.4 date asset asset capital expense trading Jan 1 Opening balance CAD 200 USD 0 CAD 200 CAD 0 USD 0 CAD 0 Jan 2 1 USD==1.20CAD CAD-120 USD 100 USD 100 CAD 120 Balance CAD 80 USD 100 CAD 200 CAD 0 USD 100 CAD 120 Jan 3 1 USD==1.30CAD USD-40 CAD 52 USD-40 CAD 52 Balance CAD 80 USD 60 CAD 200 CAD 52 USD 60 CAD-68 Jan 5 1 USD==1.25CAD CAD 75 USD-60 USD-60 CAD 75 Balance CAD 155 USD 0 CAD 200 CAD 52 USD 0 CAD 07 Jan 7 Buy food CAD-20 CAD 20 Balance CAD 135 USD 0 CAD 200 CAD 72 USD 0 CAD 07 """ ldgr = Ledger(Column("Canadian cash", Cy.CAD, Role.asset, "{}"), Column("US cash", Cy.USD, Role.asset, "{}"), Column("Capital", Cy.CAD, Role.capital, "{}"), Column("Expense", Cy.CAD, Role.expense, "{}"), ref=Cy.CAD) cols = ldgr.columns self.assertIs(Status.failed, ldgr.equation.status) # row one for amount, col in zip((Dl(200), Dl(0), Dl(200), Dl(0)), ldgr.columns.values()): ldgr.commit(amount, col, ts=datetime.date(2013, 1, 1), note="Opening balance") self.assertEqual(200, ldgr.value("Canadian cash")) self.assertEqual(200, ldgr.value("Capital")) self.assertEqual(0, ldgr.value("USD trading account")) # whitebox test self.assertIs(Status.failed, ldgr.equation.status) # row two exchange = Exchange({(Cy.USD, Cy.CAD): Dl("1.2")}) for args in ldgr.adjustments(exchange): ldgr.commit(*args, ts=datetime.date(2013, 1, 2), note="1 USD = 1.20 CAD") lhs, rhs, st = ldgr.equation self.assertEqual(lhs, rhs) self.assertIs(st, Status.ok) usd = exchange.convert(120, TradePath(Cy.CAD, Cy.CAD, Cy.USD)) self.assertEqual(100, usd) ldgr.commit(-120, cols["Canadian cash"]) self.assertIs(ldgr.equation.status, Status.failed) ldgr.commit(usd, cols["US cash"]) self.assertIs(ldgr.equation.status, Status.ok) # row three exchange = Exchange({(Cy.USD, Cy.CAD): Dl("1.3")}) for args in ldgr.adjustments(exchange): ldgr.commit(*args, ts=datetime.date(2013, 1, 3), note="1 USD = 1.30 CAD") cad = exchange.convert(40, TradePath(Cy.USD, Cy.CAD, Cy.CAD)) self.assertEqual(52, cad) self.assertIs(ldgr.equation.status, Status.ok) ldgr.commit(-40, cols["US cash"]) self.assertIs(ldgr.equation.status, Status.failed) ldgr.commit(cad, cols["Expense"]) self.assertIs(ldgr.equation.status, Status.ok) # row four exchange = Exchange({(Cy.USD, Cy.CAD): Dl("1.25")}) for args in ldgr.adjustments(exchange): ldgr.commit(*args, ts=datetime.date(2013, 1, 5), note="1 USD = 1.25 CAD") cad = exchange.convert(60, TradePath(Cy.USD, Cy.CAD, Cy.CAD)) self.assertEqual(75, cad) self.assertIs(ldgr.equation.status, Status.ok) ldgr.commit(-60, cols["US cash"]) self.assertIs(ldgr.equation.status, Status.failed) ldgr.commit(cad, cols["Canadian cash"]) self.assertIs(ldgr.equation.status, Status.ok) self.assertEqual(155, ldgr.value("Canadian cash")) # row five ldgr.commit(-20, cols["Canadian cash"], note="Buy food") self.assertIs(ldgr.equation.status, Status.failed) ldgr.commit(20, cols["Expense"], note="Buy food") self.assertIs(ldgr.equation.status, Status.ok) # final balance self.assertEqual(135, ldgr.value("Canadian cash")) self.assertEqual(0, ldgr.value("US cash")) self.assertEqual(200, ldgr.value("Capital")) self.assertEqual(72, ldgr.value("Expense")) self.assertEqual(7, ldgr.value("USD trading account"))