Reference guide
Conceptual overview
currencies usd, eur=1.1, gbp=1.3
tags
group class: stocks, bonds, cash, gold
group geo: us, eu, em
assets
US_FUND
tags us, stocks=0.95, cash=0.05
price 30usd lot 10
EU_FUND
tags eu, stocks=0.95, cash=0.05
price 22usd lot 10
EM_FUND
tags em, stocks=0.95, cash=0.05
price 110usd lot 10
account Broker
default fee 0.05% min 2usd
default spread 0.2%
US_FUND 700 buy,sell
EU_FUND 200
buy,sell spread 0.3%
mintrade 100usd maxtrade 5000eur
buy 100 for *eur fee 50eur spread 0.1%
mintrade 5000eur via OTC
sell 100 for *eur fee 100eur spread 0.1%
mintrade 5000eur via OTC
EM_FUND 500 buy,sell
GOLD_FUND 100
tags gold
price 70usd buy,sell
GLOBAL_BONDS_FUND 100
price 28usd
tags us=0.4,eu=0.4,em=0.2,bonds
buy,sell
USD
EUR price *usd,*gbp
buy,sell 1000 for *usd spread 0.05% via broker
buy,sell fee 0% spread 2% via bank
GBP 10_000 tags eu,cash
transfers
group limit 50_000usd
out usd -> tax_deferred via ACH max 2500usd
out usd -> tax_deferred via WIRE max 50_000usd fee 0.2% max 50usd
group limit none
out us_fund -> tax_deferred fee 25usd
account Tax_Deferred
default fee 0.5% spread 0.2%
US_FUND 300 buy,sell
EU_FUND 100 buy,sell fee 2%
USD
transfers
in * limit 10_000usd
in * via wire fee 15usd
in us_fund fee 25usd
account Others
USD
EUR buy,sell
Coins 50 tags gold price 300usd buy,sell spread 2%
allocation
stocks ~ 50%(group)
bonds ~ 30%(group)
gold ~ 10%(group)
cash ~ 10%(total)
us ~ 50%(group)
eu ~ 25%(group)
em ~ 25%(group)
eu_fund@tax_deferred ~ 25%(tax_deferred)
tax_deferred ~15%(broker) min current+5000usd
coins ~ 25%(gold) buy
cash@broker ~ 0%(account)
At first, I present a full example for you to have a quick syntax reference and a bird-eye view over the features of the service. I suppose this to be quite self-evident, but some explanations are due and we will work everything out on a bunch of minimal cases.
The service solves the mathematical optimization problem of finding the cheapest set of transactions to bring your portfolio as close as possible to the specified allocation. In order to state the problem, you have to describe your portfolio: assets, positions, allowed transactions, their fees and limits, and the desired allocation. The allocation is specified in terms of aggregates — groups of weighted positions (usually, exposure-weighted, as in this example), and rules the aggregates must follow.
Beware the mathematical optimization. It does not try to understand what you mean by your request, but blindly and strictly follows the problem specification. If the problem admits several solutions (as it usually does), you'll get a random one regardless of its desirability to you, depending on otherwise-inconsequential details of the problem statement (such as ordering of positions and rules, for instance). You need to double-check the obtained solution and maybe adjust either the problem or the solution itself. This service is implemented on the premise that it is easier to check the solution than to calculate it by pen, paper and spreadsheet.
A minimal example
currencies usd
account Broker
US_FUND 700 price 30usd buy,sell
EU_FUND 1000 price 22usd buy,sell
EM_FUND 500 price 110usd buy,sell
USD
allocation
us_fund ~ 33%(total)
eu_fund ~ 33%(total)
em_fund ~ 33%(total)
-
currencies usd
At first, you declare all currencies used in a portfolio. The first currency in the list will be the primary currency. All calculations are being done in the primary currency, with conversions taking place only upon reading the specification and printing the results; this could introduce small numerical errors. -
account Broker
Any position should belong to some account. You may want to introduce "virtual" accounts to hold cash, physical gold, crypto, realty and the like. All names should be unique, i.e. you can't have account and asset with the same name. Names are case-insensitive ("Broker", "BROKER" and "broker" all denote the same entity), may contain only letters, numbers and underscores, and cannot start with a number. -
US_FUND 700
This is a position — the name of an asset and its quantity. Quantities may be omitted if zero. You can use underscores to improve readability of numbers ("1000000" vs "1_000_000"). Fractional quantities are allowed, but see discussion on lot sizes. By default, the algorithm operates in whole units. -
price 30usd
This specifies the accounting price of the asset. The algorithm uses accounting values to find a desired asset allocation. That is, if you have to pay 100usd to buy an asset with accounting price of 80usd, this asset value will increase only by this 80usd. -
buy,sell
You have to say which transactions are possible with the asset. If you omit this block, the algorithm will not try to buy or sell this asset. You can specify multiple buy and sell transactions with different parameters (price, spread, fee, lot size), this is discussed later on. -
US_FUND ~ 33%(total)
This is the target allocation for the asset. It is necessary to indicate the reference aggregate when using percentage values. It can be the total portfolio, some account, another asset, tag, etc. The algorithm minimizes the sum of absolute differences between actual and target allocation, subject to imposed transaction and allocation constraints. Transaction losses also regarded as allocation difference. That is, the algorithm searches for the cheapest way to achieve an allocation closest (in absolute terms) to the target, but won't improve allocation error by 100usd if it costs 101usd.
Transaction losses and currency conversions
currencies usd, eur=1.1, gbp=1.3
account Broker
default fee 0.05% min 2usd
default spread 0.2%
US_FUND 700 price 30usd buy,sell
EU_FUND 1000 price 20eur buy,sell
EM_FUND 500 price 110usd buy,sell
USD
EUR price *usd,*gbp
buy,sell 1000 for *usd spread 0.05% via broker
buy,sell fee 0% spread 2% via bank
GBP 10000
allocation
us_fund ~ 33%(total)
eu_fund ~ 33%(total)
em_fund ~ 33%(total)
-
currencies usd, eur=1.1
For each secondary currency you have to specify its exchange rate to the primary currency. You can also use inverse quotes such ascny=1/6.96
. -
default fee 0.05% min 2usd default spread 0.2%
Sets the default fee and spread for all transactions in this account that follow this lines. Can be abbreviated in a single line as "default fee 0.05% min 2usd spread 0.2%
". Full fee specification see below. -
USD EUR price *usd,*gbp buy,sell 1000 for *usd spread 0.05% via broker buy,sell fee 0% spread 2% via bank GBP 10000
There is a lot to say about this fragment:-
You don't need to specify accounting price for currencies, as it is already defined in the
currencies
block. -
The
price
block redefines accounting prices for this position. Asterisk means "calculate this value from existing information". -
You can also redefine actual prices for transaction by means of the
for
block. By default, actual transaction prices are accounting prices after applying spread. Thus, "for *usd
" makes currency exchange through broker available only for usd, and "buy,sell ... via bank
" is equivalent to "buy,sell for *usd,*gbp ... via bank
" -
Note, how fee and spread gets overridden for EUR exchange via bank.
If "
fee 0%
" is not specified, this transaction will entail the default fee. -
You don't have (and better not to) specify transactions for both sides of the exchange, exception being exchange through different currency pairs such as the following:
USD buy,sell 1000 via usd_eur EUR buy,sell 1000 via eur_usd
which means you can either exchange 1000usd for appropriate amount of eur, or 1000eur for appropriate amount of usd. "1000" is the lot size for this transaction. - TIP: Currency conversion through a bank usually entails withdrawing money to the bank account, exchanging them, and depositing back to the brokerage account; but if this transfers are immaterial to the problem, you can specify the exchange directly in the brokerage account, as in this example.
- Non-currency-exchange transactions are all the same, but all this intricacies typically arise just here.
-
You don't need to specify accounting price for currencies, as it is already defined in the
- (Tax modelling is under development.)
Transaction constraints
currencies usd, eur=1.1
account Broker
US_FUND 700 price 30usd lot 10 buy,sell
EU_FUND 1000 price 22usd
buy,sell 10 spread 0.3%
mintrade 100usd maxtrade 5000eur
buy 100 for *eur fee 50eur spread 0.1%
mintrade 5000eur via OTC
sell 100 for *eur fee 100eur spread 0.1%
mintrade 5000eur via OTC
EM_FUND 500 price 110usd buy,sell
USD
EUR buy,sell fee 0.2%
allocation
us_fund ~ 33%(total)
eu_fund ~ 33%(total)
em_fund ~ 33%(total)
-
Constraints, as other parameters, can be specified separately for buy and sell transactions. And, by means of
for
andvia
blocks, separately for different currencies and "mediums". -
"
lot 10
" — default lot size for all transactions. Unless specified otherwise, the asset will be bought and sold in multiples of this. -
"
buy,sell 10
" — "10
" is the lot size for this transaction. -
"
mintrade 100usd
", "maxtrade 100usd
" — minimum and maximum transaction volumes.
Multiple accounts
currencies usd
assets
US_FUND price 30usd lot 10
EU_FUND price 22usd lot 10
EM_FUND price 110usd lot 10
account A
default fee 0.05% spread 0.2%
US_FUND 700 buy,sell
EU_FUND 1000 buy,sell
EM_FUND 500 buy,sell
USD
transfers
group limit 50000usd
out usd -> B max 2500usd via ACH
out usd -> B max 50000usd fee 0.2% max 50usd
via WIRE
out us_fund -> B fee 25usd
account B
default fee 0.5% spread 0.2%
US_FUND 300 buy,sell
EU_FUND 100 buy,sell fee 2%
USD
transfers
in * limit 10000usd
in * via wire fee 15usd
in us_fund fee 25usd
allocation
us_fund ~ 33%(total)
eu_fund ~ 33%(total)
em_fund ~ 33%(total)
eu_fund@b ~ 25%(b)
b ~15%(a) min current+5000usd
- The optional
assets
block contains asset properties common for all accounts. If this block is omitted, the properties defined on the first occurrence of the asset will be set as default - The
transfers
block describes position transfers.out
clauses define possible outbound transfers,in
clauses specify fees and limits at the receiving account (you don't have to matchout
andin
clauses: absence of a matchingin
block just means there is no fees and limits at the receiving side). -
Transfer fees are specified and calculated exactly the same way as transaction fees.
Fees specified in the
out
clause are charged at the sending account, in thein
clause — at the receiving account. - If you can't pay the transfer fee due to imposed constraints, the transfer is impossible and this situation is not reported.
-
If you have several means of transferring an asset between accounts, you can distinguish them with the
via
block. -
in * via wire fee 15usd
*
matches all incoming assets, you can list asset names separated by comma instead.
via wire
matches only those assets which are received through the specified channel. -
If an incoming transfer matches several
in
clauses, then all of them apply (fees add up, all limits must be respected). -
group limit 50000usd
This clause specifies group limit, i.e. total volume of all transfers defined after this clause must be no more than 50000usd. Bothin
andout
transfers count. If you want to close a group, usegroup limit none
after the last transfer in the group (orgroup limit amount
to start the next). -
eu_fund@b ~ 25%(b)
It you want to specify allocation for an asset (or tag, see below) in a specific account, use "@
" sign. You could writeeu_fund@b ~ 25%(a)
, i.e. aim to haveeu_fund@b
about 25% of the "A" account value, but that would be strange. -
b ~ 15%(a) min current+5000usd
Make the algorithm try to have the value of "B" account to be 15% of the "A" account, but fund it with at least 5000usd. You can also specify desired minimum in the hard sum (min 20000usd
), or specify mandatory withdrawal (max current-5000usd
). If you have multiple minimums/maximums specified, the strictest apply. -
min
andmax
define hard limits, which are enforced whatever the cost. The service will warn you when you should relax these limits for the allocation to be feasible. It tries to find as little adjustment as possible, but it may not be the best from your point of view and may not be accurate.
Exposures
currencies usd, eur=1.1
tags
group class: stocks, bonds, cash, gold
group geo: us, eu, em
account Broker
US_FUND 700
tags us, stocks=0.95, cash=0.05
price 30usd buy,sell
EU_FUND 1000
tags eu, stocks=0.95, cash=0.05
price 22usd buy,sell
EM_FUND 500
tags em, stocks=0.95, cash=0.05
price 110usd buy,sell
GOLD_FUND 100
tags gold
price 70usd buy,sell
GLOBAL_BONDS_FUND 100
price 28usd
tags us=0.4,eu=0.4,em=0.2,bonds
buy,sell
USD tags us,cash
EUR tags eu,cash buy,sell
account Others
USD tags us,cash
EUR tags eu,cash buy,sell
Coins 50 tags gold price 300usd buy,sell spread 2%
allocation
stocks ~ 50%(group)
bonds ~ 30%(group)
cash ~ 10%(group)
gold ~ 10%(group)
us ~ 50%(group)
eu ~ 25%(group)
em ~ 25%(group)
coins ~ 25%(gold) buy
cash@broker ~ 0%(account)
- Asset allocation is rarely defined in terms of specific tickers. Usually, it is exposures that you need to achieve by allocating money to specific tickers. In this service exposures are defined by means of tags.
- At first, you have to list all the tags you're going to use.
-
group geo: us, eu, em
Tags may be grouped. A group of tags may be used as a reference aggregate, and it will have a separate chart in the "Charts" tab. Free-standing tags should be defined before tag groups. -
tags us, stocks=0.95, cash=0.05
You assign tags to assets in order to define exposures. Each asset tag has a weight, unit by default. Weights may be greater than unit and may be negative (to reflect, for instance, leveraged and inverse funds). There is no need for the grouped tags' weights to add up to a unit, as well as for each asset to belong to all groups -
us ~ 50%(group) cash@broker ~ 0%(account)
You may use keywordsgroup
andaccount
instead of actual tag group and account names to refer to the respective aggregate. You can specify allocation rules for any aggregate except tag group, and use any aggregate as a reference aggregate. Note, that it is of little sense to use total portfolio as the reference aggregate for US exposure, as a significant part of our portfolio (gold) cannot be attributed to any region. Thus, we specify that US-attributed assets should amount to 50% of only those assets that do have regional attribution. -
coins ~ 25%(gold) buy
buy
means that only buying transactions on that asset are possible (equivalent of specifyingbuy
instead ofbuy,sell
for any occurrence of this asset). You can also usesell
to prevent buying andhold
to prohibit all the trades. This constraints can also be specified for positions and accounts (restricting transactions for all positions in the respective accounts). When several constraints are imposed (even indirectly), the strictest apply. I.e. if you writeeur hold eur@broker buy
the last one will have no effect, andeur buy eur@broker sell
will makeeur@broker
non-tradeable. This constraint does not affect asset transfers.
Fee specification
The transaction fee in its full glory is specified thus:
fee 1usd + 0.01% + 1eur/unit
min 2gbp min 0.02%
max 0.05% max 1000gbp use gbp
-
1usd
— fixed part, charged per transaction;
0.01%
— variable part as percent of the transaction volume;
1eur/unit
— variable part, charged per unit of asset (not per lot!);
min 2gbp
— minimum fixed fee, charged when fixed+variable is less than the specified amount;
min 0.02%
— minimum variable fee, charged when fixed+variable is less than the specified percent of the transaction volume;
max 0.05%
— fee cap specified as percent of the transaction volume;
max 1000gbp
— absolute fee cap;
use gbp
— in which currency charge the fee (for asset transfers, see below). - You can mix different currencies in the specification, but all amounts are immediately converted to the primary currency.
-
The greater of the minimums and the lesser of the maximums applies.
Maximum take precedence over minimum.
That is:
fee = min(max(fixed+variable, fixed_min, variable_min), fixed_max, variable_max)
-
For trades, fee is charged in the price currency.
For money transfers — in the currency being transferred.
For other asset transfers — in the currency specified in the
use
block.
Allocation rules
target_aggregate
~ 15%(ref_aggregate)
~ 10_000usd
~ 500units
~ current+5000usd
~ current-5000usd
min -10_000usd
max 10_000usd
~min 10_000eur
min 500units
min 15%(ref_aggregate)
min current
min current+5000usd
min current-5000usd
buy
sell
hold
-
The pattern is
[target_aggregate] [rule] [rule] [rule]
. Note the absence of commas between rules. -
A
[rule]
is either one ofbuy
,sell
,hold
, or constructed as follows:[type] [value]
.
Where[type]
is one of~
— "target", the algorithm will minimize the deviation from the value,min
— "hard" minimum, enforced by the algorithm, may be reported as infeasiblemax
— "hard" maximum, enforced by the algorithm, may be reported as infeasible,~min
— "soft" minimum, the algorithm minimizes the negative deviation from the value,~max
— "soft" maximum, the algorithm minimizes the positive deviation from the value.
[value]
is one of10_000usd
— currency value (may be negative),500units
— quantity in units of the asset (may be negative),current
— current value of the aggregate,current+5000usd
— current value of the aggregate plus (minus) currency value,15%([ref_aggregate])
— percentage value of the reference aggregate.
[ref_aggregate]
) may betotal
— total portfolio value,account
— total value of the respective account (if the target aggregate specifies account),group
— total value of the respective tag group (for tags),[aggregate name]
— i.e. the name of an account, asset, position ([asset name]@[account name]
), tag, tag-in-account ([tag name]@[account name]
).