Technical notes
How rebalancing works
The portfolio specification gets transformed to a mixed-integer programming problem, fed into a specialized solver, and the obtained solution is decoded as a list of transactions.
The solver minimizes the SUM of absolute allocation errors and all transaction losses subject to specified constraints. Above all, it means two things:
- an allocation error of 50$ is always the allocation error of 50$, regardless of whether it relates to an asset of 100$ or 100,000$ in value, the algorithm has no preference in «assigning» the errors to assets of higher values, thus decreasing relative error;
- the algorithm also has no incentive in evenly «distributing» errors between assets: if a 100$ error has to be distributed between two assets, it may end up as 100—0, 0—100, or anything in-between.
Why text?
In short, it's too much data in the spec that renders «traditional» input forms impractical. Just look at the fee parameters: it is alone a quite complex form, and mostly empty. So, instead of dozens of mostly empty forms, there is a dense text, allowing you to glance over all your portfolio specification at once. And no data is taken hostage.
Also, it makes creating and using documentation much easier: I just share particular specification snippets which you can quickly copy-paste and adjust, instead of following step-by-step screenshot guides which are very tedious to prepare and keep up to date.
Architecture overview
Authentication overview
Thus, users' credentials exist only for a short amount of time in the /login
page and never sent to the server in any form. The public/private keypair and the session key are stored in the service worker's memory which is not exposed through its API and thus inaccessible from the outside.
The session key is short-lived: the server periodically resets it, requiring the service worker to obtain a new key transparently to the user.
Nonces protect requests from replay attacks.
Signup works the same: the request to store user's public key goes to a protected resource, thus the server immediately checks that it is properly signed by the holder of the respective private key.
Data storage
Portfolio data is stored encrypted. The scheme is as follows (performed inside the session worker).
- Derive public/private keypair upon login.
- Generate a random encryption key (EK) for each request to encrypt data.
- Encrypt the data with EK, yielding ED (encrypted data).
- Generate an ephemeral keypair, from which it needs only the pubkey key (EPK)
- Derive a session key (SK) from EPK and the user's private key.
- Wrap EK with SK, yielding WK.
- Return ED + EPK + WK, which can be stored in untrusted storage.
To decrypt the data the following procedure is performed:
- Derive the session key (SK) from the stored EPK and the user's private key.
- Unwrap the EK from the stored WK with SK.
- Decrypt the ED with EK.
Such a sophisticated scheme is used to allow users (primarily, business users with lots of portfolios) change their credentials without the need to reencrypt all their portfolios: only 128-bit WK depends on it. Also, it allows sharing/transferring portfolios between corporate users without a trusted third-party for exchanging secrets: replacing EPK with the addressee's public key makes SK derivable only by that addressee.
Thr whole picture is as follows. Red background marks first-hand private data, green background — safe-to-publish data, blue border — pieces of data stored in the DB, red border — data stored by the user.