[
{
"name": "a 60/40 portfolio exactly on target",
"args": [
[
{
"id": "EQUITY",
"value": {
"minor": 600000,
"currency": "GBP"
},
"targetBasisPoints": 6000
},
{
"id": "BONDS",
"value": {
"minor": 400000,
"currency": "GBP"
},
"targetBasisPoints": 4000
}
]
],
"expect": {
"total": {
"minor": 1000000,
"currency": "GBP"
},
"holdings": [
{
"id": "EQUITY",
"value": {
"minor": 600000,
"currency": "GBP"
},
"weightBasisPoints": 6000,
"targetBasisPoints": 6000,
"driftBasisPoints": 0,
"targetValue": {
"minor": 600000,
"currency": "GBP"
},
"driftValue": {
"minor": 0,
"currency": "GBP"
}
},
{
"id": "BONDS",
"value": {
"minor": 400000,
"currency": "GBP"
},
"weightBasisPoints": 4000,
"targetBasisPoints": 4000,
"driftBasisPoints": 0,
"targetValue": {
"minor": 400000,
"currency": "GBP"
},
"driftValue": {
"minor": 0,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 0
}
},
{
"name": "equities have run up to 70% against a 60% target",
"args": [
[
{
"id": "EQUITY",
"value": {
"minor": 700000,
"currency": "GBP"
},
"targetBasisPoints": 6000
},
{
"id": "BONDS",
"value": {
"minor": 300000,
"currency": "GBP"
},
"targetBasisPoints": 4000
}
]
],
"expect": {
"total": {
"minor": 1000000,
"currency": "GBP"
},
"holdings": [
{
"id": "EQUITY",
"value": {
"minor": 700000,
"currency": "GBP"
},
"weightBasisPoints": 7000,
"targetBasisPoints": 6000,
"driftBasisPoints": 1000,
"targetValue": {
"minor": 600000,
"currency": "GBP"
},
"driftValue": {
"minor": 100000,
"currency": "GBP"
}
},
{
"id": "BONDS",
"value": {
"minor": 300000,
"currency": "GBP"
},
"weightBasisPoints": 3000,
"targetBasisPoints": 4000,
"driftBasisPoints": -1000,
"targetValue": {
"minor": 400000,
"currency": "GBP"
},
"driftValue": {
"minor": -100000,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 1000
}
},
{
"name": "three equal holdings are 3333 bp each and the weights do not sum to 10000",
"args": [
[
{
"id": "A",
"value": {
"minor": 100,
"currency": "GBP"
},
"targetBasisPoints": 3333
},
{
"id": "B",
"value": {
"minor": 100,
"currency": "GBP"
},
"targetBasisPoints": 3333
},
{
"id": "C",
"value": {
"minor": 100,
"currency": "GBP"
},
"targetBasisPoints": 3334
}
]
],
"expect": {
"total": {
"minor": 300,
"currency": "GBP"
},
"holdings": [
{
"id": "A",
"value": {
"minor": 100,
"currency": "GBP"
},
"weightBasisPoints": 3333,
"targetBasisPoints": 3333,
"driftBasisPoints": 0,
"targetValue": {
"minor": 100,
"currency": "GBP"
},
"driftValue": {
"minor": 0,
"currency": "GBP"
}
},
{
"id": "B",
"value": {
"minor": 100,
"currency": "GBP"
},
"weightBasisPoints": 3333,
"targetBasisPoints": 3333,
"driftBasisPoints": 0,
"targetValue": {
"minor": 100,
"currency": "GBP"
},
"driftValue": {
"minor": 0,
"currency": "GBP"
}
},
{
"id": "C",
"value": {
"minor": 100,
"currency": "GBP"
},
"weightBasisPoints": 3333,
"targetBasisPoints": 3334,
"driftBasisPoints": -1,
"targetValue": {
"minor": 100,
"currency": "GBP"
},
"driftValue": {
"minor": 0,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 1
}
},
{
"name": "half a basis point rounds up for both holdings, so the weights sum to 10001",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 0
},
{
"id": "B",
"value": {
"minor": 19999,
"currency": "GBP"
},
"targetBasisPoints": 10000
}
]
],
"expect": {
"total": {
"minor": 20000,
"currency": "GBP"
},
"holdings": [
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"weightBasisPoints": 1,
"targetBasisPoints": 0,
"driftBasisPoints": 1,
"targetValue": {
"minor": 0,
"currency": "GBP"
},
"driftValue": {
"minor": 1,
"currency": "GBP"
}
},
{
"id": "B",
"value": {
"minor": 19999,
"currency": "GBP"
},
"weightBasisPoints": 10000,
"targetBasisPoints": 10000,
"driftBasisPoints": -1,
"targetValue": {
"minor": 20000,
"currency": "GBP"
},
"driftValue": {
"minor": -1,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 1
}
},
{
"name": "drift comes from the exact values, not weight minus target: -0.5 bp is -1, not 1 - 1 = 0",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 1
},
{
"id": "B",
"value": {
"minor": 19999,
"currency": "GBP"
},
"targetBasisPoints": 9999
}
]
],
"expect": {
"total": {
"minor": 20000,
"currency": "GBP"
},
"holdings": [
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"weightBasisPoints": 1,
"targetBasisPoints": 1,
"driftBasisPoints": -1,
"targetValue": {
"minor": 2,
"currency": "GBP"
},
"driftValue": {
"minor": -1,
"currency": "GBP"
}
},
{
"id": "B",
"value": {
"minor": 19999,
"currency": "GBP"
},
"weightBasisPoints": 10000,
"targetBasisPoints": 9999,
"driftBasisPoints": 1,
"targetValue": {
"minor": 19998,
"currency": "GBP"
},
"driftValue": {
"minor": 1,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 1
}
},
{
"name": "a new fund worth nothing yet is fully underweight",
"args": [
[
{
"id": "OLD",
"value": {
"minor": 500000,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "NEW",
"value": {
"minor": 0,
"currency": "GBP"
},
"targetBasisPoints": 5000
}
]
],
"expect": {
"total": {
"minor": 500000,
"currency": "GBP"
},
"holdings": [
{
"id": "OLD",
"value": {
"minor": 500000,
"currency": "GBP"
},
"weightBasisPoints": 10000,
"targetBasisPoints": 5000,
"driftBasisPoints": 5000,
"targetValue": {
"minor": 250000,
"currency": "GBP"
},
"driftValue": {
"minor": 250000,
"currency": "GBP"
}
},
{
"id": "NEW",
"value": {
"minor": 0,
"currency": "GBP"
},
"weightBasisPoints": 0,
"targetBasisPoints": 5000,
"driftBasisPoints": -5000,
"targetValue": {
"minor": 250000,
"currency": "GBP"
},
"driftValue": {
"minor": -250000,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 5000
}
},
{
"name": "a holding with a zero target is all drift",
"args": [
[
{
"id": "KEEP",
"value": {
"minor": 750000,
"currency": "GBP"
},
"targetBasisPoints": 10000
},
{
"id": "SELL",
"value": {
"minor": 250000,
"currency": "GBP"
},
"targetBasisPoints": 0
}
]
],
"expect": {
"total": {
"minor": 1000000,
"currency": "GBP"
},
"holdings": [
{
"id": "KEEP",
"value": {
"minor": 750000,
"currency": "GBP"
},
"weightBasisPoints": 7500,
"targetBasisPoints": 10000,
"driftBasisPoints": -2500,
"targetValue": {
"minor": 1000000,
"currency": "GBP"
},
"driftValue": {
"minor": -250000,
"currency": "GBP"
}
},
{
"id": "SELL",
"value": {
"minor": 250000,
"currency": "GBP"
},
"weightBasisPoints": 2500,
"targetBasisPoints": 0,
"driftBasisPoints": 2500,
"targetValue": {
"minor": 0,
"currency": "GBP"
},
"driftValue": {
"minor": 250000,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 2500
}
},
{
"name": "values whose x10000 passes 2^53 stay exact",
"args": [
[
{
"id": "A",
"value": {
"minor": 900000000000000,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "B",
"value": {
"minor": 100000000000000,
"currency": "GBP"
},
"targetBasisPoints": 5000
}
]
],
"expect": {
"total": {
"minor": 1000000000000000,
"currency": "GBP"
},
"holdings": [
{
"id": "A",
"value": {
"minor": 900000000000000,
"currency": "GBP"
},
"weightBasisPoints": 9000,
"targetBasisPoints": 5000,
"driftBasisPoints": 4000,
"targetValue": {
"minor": 500000000000000,
"currency": "GBP"
},
"driftValue": {
"minor": 400000000000000,
"currency": "GBP"
}
},
{
"id": "B",
"value": {
"minor": 100000000000000,
"currency": "GBP"
},
"weightBasisPoints": 1000,
"targetBasisPoints": 5000,
"driftBasisPoints": -4000,
"targetValue": {
"minor": 500000000000000,
"currency": "GBP"
},
"driftValue": {
"minor": -400000000000000,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 4000
}
},
{
"name": "a single holding is the whole portfolio",
"args": [
[
{
"id": "ONLY",
"value": {
"minor": 12345,
"currency": "GBP"
},
"targetBasisPoints": 10000
}
]
],
"expect": {
"total": {
"minor": 12345,
"currency": "GBP"
},
"holdings": [
{
"id": "ONLY",
"value": {
"minor": 12345,
"currency": "GBP"
},
"weightBasisPoints": 10000,
"targetBasisPoints": 10000,
"driftBasisPoints": 0,
"targetValue": {
"minor": 12345,
"currency": "GBP"
},
"driftValue": {
"minor": 0,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 0
}
},
{
"name": "a third of a basis point rounds down both ways",
"args": [
[
{
"id": "A",
"value": {
"minor": 33333,
"currency": "GBP"
},
"targetBasisPoints": 3000
},
{
"id": "B",
"value": {
"minor": 66667,
"currency": "GBP"
},
"targetBasisPoints": 7000
}
]
],
"expect": {
"total": {
"minor": 100000,
"currency": "GBP"
},
"holdings": [
{
"id": "A",
"value": {
"minor": 33333,
"currency": "GBP"
},
"weightBasisPoints": 3333,
"targetBasisPoints": 3000,
"driftBasisPoints": 333,
"targetValue": {
"minor": 30000,
"currency": "GBP"
},
"driftValue": {
"minor": 3333,
"currency": "GBP"
}
},
{
"id": "B",
"value": {
"minor": 66667,
"currency": "GBP"
},
"weightBasisPoints": 6667,
"targetBasisPoints": 7000,
"driftBasisPoints": -333,
"targetValue": {
"minor": 70000,
"currency": "GBP"
},
"driftValue": {
"minor": -3333,
"currency": "GBP"
}
}
],
"maxAbsDriftBasisPoints": 333
}
},
{
"name": "an empty portfolio is an error",
"args": [
[]
],
"expectError": "holdings must not be empty"
},
{
"name": "the same id twice is an error",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 5000
}
]
],
"expectError": "duplicate holding id \"A\""
},
{
"name": "targets summing to 9999 are an error",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "B",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 4999
}
]
],
"expectError": "targets must sum to 10000 basis points, received 9999"
},
{
"name": "mixed currencies are an error",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "B",
"value": {
"minor": 1,
"currency": "USD"
},
"targetBasisPoints": 5000
}
]
],
"expectError": "currency mismatch: GBP and USD"
},
{
"name": "a negative value is an error",
"args": [
[
{
"id": "A",
"value": {
"minor": -1,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "B",
"value": {
"minor": 10,
"currency": "GBP"
},
"targetBasisPoints": 5000
}
]
],
"expectError": "holding values must be whole minor units, 0 or more"
},
{
"name": "a fractional minor unit is an error",
"args": [
[
{
"id": "A",
"value": {
"minor": 1.5,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "B",
"value": {
"minor": 10,
"currency": "GBP"
},
"targetBasisPoints": 5000
}
]
],
"expectError": "holding values must be whole minor units, 0 or more"
},
{
"name": "a target above 10000 is an error even if the sum works out",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 10001
},
{
"id": "B",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": -1
}
]
],
"expectError": "targetBasisPoints must be a whole number from 0 to 10000"
},
{
"name": "a fractional target is an error",
"args": [
[
{
"id": "A",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 2500.5
},
{
"id": "B",
"value": {
"minor": 1,
"currency": "GBP"
},
"targetBasisPoints": 7499.5
}
]
],
"expectError": "targetBasisPoints must be a whole number from 0 to 10000"
},
{
"name": "a portfolio worth nothing is an error",
"args": [
[
{
"id": "A",
"value": {
"minor": 0,
"currency": "GBP"
},
"targetBasisPoints": 5000
},
{
"id": "B",
"value": {
"minor": 0,
"currency": "GBP"
},
"targetBasisPoints": 5000
}
]
],
"expectError": "the portfolio total must be greater than zero"
}
]