Amatino API v0.0.9 now live

A new version of the Amatino API is now live around the world. 0.0.9 is substantially backwards compatible with 0.0.8, but you should not rely on backwards compatibility during the 0.0.X series of releases.

Amatino API v0.0.8 now live

A new version of the Amatino API is live in all regions. API 0.0.8 may be substantially backward compatible with 0.0.7, however, is not tested as such and relying on backwards compatibility during these 0.0.X releases is not recommended.

  • Fixed a bug which could cause a stale, cached Performance or Position to be returned after a Transaction insertion
  • Fixed a bug causing Custom Unit update requests to fail, returning a 500 code.
  • Account objects now feature a ‘Children’ parameter, which contains integer IDs of all direct child Accounts.
  • Fixed a rare condition wherein internal telemetry recording could fail due to a unique key constraint violation, causing the API to spew 500 errors in response to any request
  • Substantial code-style enhancements in the core API to ease maintainability
  • Improved test coverage over rare edge cases in Account operations

Amatino JS 0.0.14 Released

A tiny update has been released for Amatino’s Node library.  0.0.14 fixes a silly bug in the inbuilt Node version enforcement script. The script is run after installation, and was supposed to stop Node versions lower than 10.4 from running Amatino JS. Instead it was stopping versions greater than 11.0 from running it!

Amatino JS 0.0.14 is available on NPM and on GitHub.

Amatino JS 0.0.13 Released

A new version of the Amatino Node.js library is now available. 0.0.13 addresses a big issue that has plagued previous Amatino JS versions, and fixes one other nasty bug:

  • Decode large integers as BigInt rather than hacking them into String
  • Encode Date month properly (previously the previous month was encoded)

When it comes to large integers, JavaScript is a bit of a minefield. Until BigInt came along, JS had no native way of dealing with integers larger than 53 bits.

Internally, the Amatino API only thinks in 64-bit integers and arbitrary-precision numbers. Floats & lower-width integers are absent.

These 64-bit integers flow out into the public domain as IDs of various objects. For example, Session IDs and User IDs are random 64-bit integers. If your Entity is extremely large, you might also encounter them as IDs for Transactions.

It is therefore critical that any Amatino client library be able to understand 64-bit integers. So what to do with JavaScript, whose native number type is 53 bits wide? At first, Amatino JS translated them to String, and sent them back to the API as JSON Strings. This was a huge, awful hack involving a flakey Regular Expression.

Surprise surprise, this caused problems for customers. We are very sorry for that. 0.0.13 solves the problem by taking advantage of the “new” native BigInt type. BigInts arrived in Google V8 version 6.7, have been available in Node since version 10.4.

Consequently, Node.js 10.4 is now the minimum required version for a project that includes Amatino JS.

Because JavaScript wants to be a constant barrel of laughs, the native JSON library cannot serialise or deserialise BigInt. We therefore owe big thanks to Andrey Sidorov, whose MIT licensed json-bigint project we adapted to handle the relevant JSON operations.

Installation & Usage

You can install Amatino JS via NPM. For more information about NPM, check out npmjs.com.

$ npm install amatino

Amatino classes may then be accessed by requiring Amatino:

const Amatino = require('Amatino'); Amatino.Transaction.create(...);

If you already have Amatino JS installed, you can update it by executing:

$ npm update Amatino

Take care – This operation may not update the Amatino version number in package.json. You may need to change that manually.

Amatino Python 0.0.10 Released

Amatino Python 0.0.10 has been released! 0.0.10 is all about balance. 0.0.10 is backward compatible with 0.0.7. 0.0.8 and 0.0.9 were skipped because… software. Changes in 0.0.10:

  • Add Balance class
  • Add RecursiveBalance class
  • Add tests for Balance & RecursiveBalance
  • Resolve bug causing amounts > 1,000 units to raise errors on retrieval

The new Balance & RecursiveBalance classes map to the Amatino API Balance & RecursiveBalance objects. They both have the same .retrieve() method signature…

balance = Balance.retrieve(
   entity=mega_corporation,
   account=current_assets,
   balance_time=datetime.utcnow(),
   denomination=us_dollars
)

… Wherein balance_time is optional (defaults to “now”) and denomination is optional (defaults to account.denomination).

For detailed documentation of the properties and methods of these new classes, check out the Amatino Python Documentation.

You can install Amatino via PyPi:

$ pip install amatino

Or, if you already have Amatino Python installed, upgrade:

$ pip install --upgrade amatino

Amatino Swift 0.0.10 Released

A new version of Amatino Swift has been released. 0.0.10 adds some Custom Unit capabilities, slims some method signatures, and various smaller bits and pieces.

Note that release 0.0.9 was skipped for reasons of… science. 0.0.8 is the previously released Swift library version.

  • Big breaking change: Session is no longer required as an argument for Performance, Position, Transaction, Balance, and RecursiveBalance
  • Build out the previously useless CustomUnit, including .retrieve().create(), .createMany(), and update() methods
  • Added unit tests for new CustomUnit methods.
  • Simplify internal AmatinoObject protocol (no change to public API)
  • Entity now conforms to Equatable protocol
  • Add Entity.delete() method
  • Add EntityList object
  • Fixed a bug causing Ledger and RecursiveLedger iterators to skip the first row in the Ledger

Amatino Python 0.0.7 Released

Amatino Python 0.0.7 has been released! This is a major new release, introducing a vast array of capabilities. It is not backwards compatible with 0.0.6. You can install Amatino via PyPi:

$ pip install amatino

Or, if you already have Amatino Python installed, upgrade:

$ pip install --upgrade amatino

Here’s the full list of changes:

  • Added Entity class including .create(), .retrieve()
  • Added Account class including .create(), .retrieve(), .update()
  • Added Transaction class including .create(), .retrieve(), .update(), .delete()
  • Added Entry class including various convenience initialisers
  • Added GlobalUnit class including .retrieve()
  • Added CustomUnit class including .create(), .retrieve()
  • Added User class including .retrieve()
  • Added Ledger & RecursiveLedger classes
  • Added internal Denomination abstract class
  • Added internal enumeration HTTPMethod
  • Added internal interface Encodable
  • Added some internal error types to provide more robust error explanations
  • Added tests for new classes
  • Removed AmatinoAlpha class & attendant tests

The high level

0.0.7 is the first Amatino Python release to include expressive, object-oriented syntax. Previous releases required manual composition of requests using the AmatinoAlpha object.

Documentation

So many new goodies. But how do we use them? Documentation to the rescue! All the new classes included in 0.0.7 are documented in Amatino Python’s GitHub Wiki. For example, you can check out the Transaction page to see all the Transaction class’s properties and methods.

The future

The most glaring omissions are 0.0.7 are probably Balance, Position, and Performance. Expect 0.0.8 to add those bad boys in the near future.

Enjoy!

– Hugh

Amatino JS 0.0.12 Released

Amatino’s Node.js library has receive a big ‘ol update. 0.0.12 lifts Amatino JS out of bare-bones alpha territory. New classes allow you to build accounting & finance functions into Node.js applications.

0.0.12 is by no means a ‘feature complete’ or beta release. Most Amatino services still lack dedicated classes. However, it is a major step towards such a release. To see plans for 0.0.13 and beyond, check out the newly populated GitHub issue tracker, and Projects page within which future work is organised into planned releases.

New capabilities

Amatino JS now offers the following classes:

Allowing you to easily access and manipulate the `Primary Objects’ discussed in Amatino’s HTTP documentation.

Amatino Javascript Documentation

This release includes the first version of Amatino’s Javascript documentation. The docs are hosted on the Amatino JS GitHub wiki. They provide comprehensive reference for all properties and methods, and example code.

Screenshot from the Amatino JS docs Account page

Installation & Usage

You can install Amatino JS via NPM. For more information about NPM, check out npmjs.com.

$ npm install amatino

Amatino classes may then be accessed by requiring Amatino:

const Amatino = require('Amatino');
Amatino.Transaction.create(...);

The Amatino JS Readme has been updated with a getting-started guide, including example code showing you how to start utilising Amatino services. Check it out on the Amatino JS GitHub page.

What’s next?

Check out the Amatino JS Projects page to see the roadmap for future releases. These plans are totally in flux: Feel free to contact me via Twitter (@hugh_jeremy), email (hugh@amatino.io), or on the Amatino discussion forums, and tell me what you would like to see next.

Special thanks must go to James Robb (jamesrobb.co.uk). Over the past few weeks, James has provided substantial and invaluable advice about how to move the Amatino JS project forward. Thank you James!

– Hugh

 

 

On Prices

The upcoming API 0.0.8 release targets Global Units, Custom Units, and a new Price object that bridges them. It is forcing me to consider some difficult questions.

Amatino’s double-entry data model adopts a ‘quantum mechanics’ approach:  Transactions are the atomic units of all financial information, but they themselves are composed of the more fundamental Entry object, with which we never directly interact. This approach allows financial data to be stored as arbitrary precision numbers in their native denomination.

It also means that the data model does not inherently satisfy the double-entry accounting equation. If external constraints are not applied, it would be possible to store an unbalanced Transaction: The composing Entries may not add up to zero, and the equation would not hold.

Obviously, Amatino is designed with stringent constraints. Attempt to insert an unbalanced Transaction and the digits ‘400’ will present themselves quick smart. But what if a Transaction balance is changed after it is inserted?

How could this happen? It is a matter of relativity. Say you create a Transaction (TX) worth 1 U.S. Dollar (USD) with Entries party to two Accounts: One denominated in USD, and one denominated in Woozlewozzles (WZL). WZL being some Custom Unit you have fed to Amatino.

Perhaps TX is created on 1 Jan 2018, dated at 1 Jan 2018, and at that time, the last WZL / USD price you provided was for 31 Dec 2017, at 2 WZL = 1 USD. Amatino will eat TX and store one Entry for 1 USD, and one Entry for 2 WZL.

Now suppose that on 2 Jan 2018, you have access to new price data. You supply Amatino with a 1 Jan 2018 WZL / USD price of 1 WZL = 1 USD. Ceteris paribus, TX is now unbalanced: Attempt to retrieve TX and Amatino will compute output using the price with time closest-to-but-less-than TX time: 1 Jan 2018.

That yields a WZL entry with double the value that it had at Transaction entry. The double-entry equation is violated and the universe (presumably) implodes.

What’s the solution? The two I am working with right now are:

1. Anchors

When creating a Transaction, a client may specify some (but not all) constituent Entries as being ‘anchors’. When a new Price is inserted, Amatino looks for any Transactions with Entries party to an Account denominated in the Priced unit, with an effective time less than the next most recent Price, and greater-than-or-equal to the new Price.

Amatino then calculates the difference between the old balance and the new balance based on the new Price. That difference is distributed proportionally across any (or the only) Entry that is not marked as being an anchor.

One advantage of Anchors is that they would be compatible with future-dated Transactions with heterogeneous Global Unit denominations.

2. Blind Repair

Similarly to solution (1), Blind Repair would look for any Transactions affected by a new Price. Instead of applying the difference in balance to specially identified Entries, Amatino applies the difference to any Entry in the Priced unit.

One advantage of Blind Repair is that it does not add new complexity to the Transaction model. Anchors would require implicit or explicit decision making on every Transaction entry.

Blind Repair would not be compatible with future-dated Transactions with heterogenous Global Unit denominations. Global Unit prices are updated metronomically at ~1800 UTC each trading day. If a Transaction contained Entries party to say, USD and Euros, how would Blind Repair choose which Entries to adjust? I don’t see a way to make the process deterministic.

What to do?

Right now, I am leaning towards choosing Blind Repair. I would combine it with a new restriction: Transactions cannot be future-dated when they are denominated in heterogenous units where one of those units is a Global Unit.

It will be frustrating to be unable to conveniently future-date known upcoming or recurring Transactions with such denominations. However, I think the increased complexity of Anchors means they are not a viable alternative.

Have thoughts on a third way? Let me know in the comments!

– Hugh

 

Amatino Swift 0.0.8 Released

A new version of Amatino Swift has been released. 0.0.8 makes Amatino Swift CocoaPods compatible. You can now install Amatino by adding it to your Podfile:

pod 'Amatino', '>= 0.0.8'

The underlying library is unchanged. Here’s the full changelog:

  • Added Amatino.podspec
  • Changed macOS target to 10.10 (arbitrary at this point)
  • Changed iOS target to 10.3 (arbitrary at this point)
  • Added MIT license
  • Updated readme.md to reflect latest development of the library

– Hugh