Open rafabap opened 7 years ago
@rafabap Let's start with the Book
interface. First, I do not understand the terminology. A Book
seems to be a collection of Account
(or Contract
) objects in which case why not call this a BalanceSheet
? Second if a Book
is just a collection of contracts then I think we should only allow adding/removing of contracts from the Book
as well as valuing assets liabilities and equity. Logic for updating the value of a particular contract should be pushed elsewhere.
Excuse the Scala, but something like the following...
abstract class Contract {
/** agent for whom the contract is a liability */
def issuer: Agent
/** agent for whom the contract is an asset */
def counterparty: Agent
/** Objective value of a contract */
def faceValue: Double
}
/** Immutable storage container for a particular agent's contracts. */
class BalanceSheet[+C <: Contract] private(agent: UUID, contracts: GenSet[C] ) {
/** Returns a new BalanceSheet with an additional contract .*/
def add[C1 >: C](contract: C1): BalanceSheet[C1] = {
new BalanceSheet(agent, contracts + contract)
}
/** Returns a new BalanceSheet after removing a particular contact. */
def remove(contract: C): BalanceSheet[C] = {
new BalanceSheet(agent, contracts - contract)
}
/** Collection of contracts that are assets. */
def assets: GenSet[C] = {
contracts.filter(contract => contract.counterparty == agent)
}
/** Collection of contracts that are liabilities. */
def liabilities: GenSet[C] = {
contracts.filter(contract => contract.issuer == agent)
}
/** The value of equity is just the difference between the value of assets and the value of liabilities.
* @note the value of equity is subjective and depends on the value function `v` used to value the
* underlying contracts.
*/
def equity(v: (Contract) => Double): Double = {
assets.map(v).sum - liabilities.map(v).sum
}
/** Leverage ratio */
def leverage(v: (Contract) => Double): Double = {
assets.map(v).sum / equity(v)
}
}
@rafabap I am also confused about the difference between Contract
and an Account
.
My most general comment is that I find the terminology very confusing. I generally do not think of Asset
, Liability
and Equity
as being types of Accounts
. But might just be me.
I guess you could have something like...
class DepositAccount private(issuer: UUID, counterparty: UUID, initialDeposit: Double) extends Contract {
val faceValue = initialDeposit
def debit(value: Double): DepositAccount = {
new DepositAccount(issuer, counterparty, initialDeposit - value)
}
def credit(value: Double): DepositAccount = {
new DepositAccount(issuer, counterparty, initialDeposit + value)
}
}
val agent: UUID = ???
val bank: UUID = ???
val deposit = DepositContract(bank, agent, 1e6)
in the above
@rafabap I just realized that Book
used to be called Ledger
! I much prefer Ledger
as it makes good use of standard accounting terminology (which has been picked up by the blockchain community which I think is useful).
@rafabap Some specific comments about the Account
class.
UUID
then String
for the type. Enum
to model different account types? Is the Enum
values just to allow you to switch behavior depending on account type?Action
type imported from? Is this a Java type? Or has this ours?@rafabap Perhaps my lack of comfort with your terminology stems from my being used to Perry Mehrling's terminology. I am reading through the Double-Entry Book-Keeping Wikipedia entry to try and familiarize myself with your terms. Is this the best source?
@davidrpugh sorry for the confusion! Just a few pints to clarify:
1) double-entry The Wikipedia article is one of the best resources I've found. The problem is that although the rules are consistent across sources, the terminology isn't! I'm happy to go back to using Ledger rather than Book.
The types of Account only matter when defining the sign of debits and credits.
2) double entry vs Inventories
I see our accounting system as a hybrid composed of two parts. The first is the double entry rules, which requires separate accounts implementing their debits and credits. The second is the inventory: a way to keep lists of contracts.
My solution is to combine the two by starting with a standard double-entry ledger havjng a few accounts, and then rather than having a single inventory for the agent, I split it in smaller inventories, each associated to one account. In addition, for clarity, I force that each account includes only one type of contract in its inventory.
@rafabap and @bherd Based on our discussion today we decided to move forward with a message passing solution for handling interaction between Ledger
/ Book
and Transactions
, etc. I think we should take a hard look at Akka. Existence of widely used Java and Scala APIs is nice and using the Actor model as our concurrency solution will help constrain our design space in general...
Hi all, I have implemented most of the comments received so far and during the code review. The concurrent implementation of the Ledger
is left for a future date.
I have followed David's advice and decided to split the inventories from the Accounts. Therefore, a Ledger
has, on the one hand, a set of accounts; and on the other hand, an inventory of contracts (the inventory is split into assets and liabilities for convenience).
Searching etc. of the inventory is done using functional calls as suggested by Ben.
The invariants provided by the framework are:
Hybrid accounting system that uses inventories and double-entry accounting.
The Double-entry is simplified so that it uses only stock accounts (ASSETS, LIABILITIES, EQUITY) and ignores flow accounts (INCOME, EXPENSES). Each account has an inventory of contracts.
Each account can hold only one type of contract in its inventory.
The Agents interact with their accounts via a Book, that provides a series of operations given in BookAPI.