@reserve-protocol/dtf-rebalance-lib 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/numbers.d.ts +9 -8
- package/dist/numbers.js +9 -7
- package/dist/open-auction.js +36 -37
- package/dist/start-rebalance.js +8 -6
- package/dist/utils.js +5 -3
- package/package.json +1 -1
package/dist/numbers.d.ts
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
import
|
1
|
+
import DecimalLight from 'decimal.js-light';
|
2
|
+
import type { Decimal as DecimalType } from 'decimal.js-light';
|
2
3
|
export declare const D27n: bigint;
|
3
4
|
export declare const D18n: bigint;
|
4
5
|
export declare const D9n: bigint;
|
5
|
-
export declare const D27d:
|
6
|
-
export declare const D18d:
|
7
|
-
export declare const D9d:
|
8
|
-
export declare const ZERO:
|
9
|
-
export declare const ONE:
|
10
|
-
export declare const TWO:
|
11
|
-
export declare const bn: (str: string |
|
6
|
+
export declare const D27d: DecimalType;
|
7
|
+
export declare const D18d: DecimalType;
|
8
|
+
export declare const D9d: DecimalType;
|
9
|
+
export declare const ZERO: DecimalLight;
|
10
|
+
export declare const ONE: DecimalLight;
|
11
|
+
export declare const TWO: DecimalLight;
|
12
|
+
export declare const bn: (str: string | DecimalType) => bigint;
|
package/dist/numbers.js
CHANGED
@@ -5,16 +5,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
exports.bn = exports.TWO = exports.ONE = exports.ZERO = exports.D9d = exports.D18d = exports.D27d = exports.D9n = exports.D18n = exports.D27n = void 0;
|
7
7
|
const decimal_js_light_1 = __importDefault(require("decimal.js-light"));
|
8
|
+
// Create a local Decimal constructor with custom precision
|
9
|
+
const Decimal = decimal_js_light_1.default.clone({ precision: 100 });
|
8
10
|
exports.D27n = 10n ** 27n;
|
9
11
|
exports.D18n = 10n ** 18n;
|
10
12
|
exports.D9n = 10n ** 9n;
|
11
|
-
exports.D27d = new
|
12
|
-
exports.D18d = new
|
13
|
-
exports.D9d = new
|
14
|
-
exports.ZERO = new
|
15
|
-
exports.ONE = new
|
16
|
-
exports.TWO = new
|
13
|
+
exports.D27d = new Decimal('1e27');
|
14
|
+
exports.D18d = new Decimal('1e18');
|
15
|
+
exports.D9d = new Decimal('1e9');
|
16
|
+
exports.ZERO = new Decimal('0');
|
17
|
+
exports.ONE = new Decimal('1');
|
18
|
+
exports.TWO = new Decimal('2');
|
17
19
|
const bn = (str) => {
|
18
|
-
return BigInt(new
|
20
|
+
return BigInt(new Decimal(str).toFixed(0));
|
19
21
|
};
|
20
22
|
exports.bn = bn;
|
package/dist/open-auction.js
CHANGED
@@ -7,7 +7,8 @@ exports.getOpenAuction = exports.getTargetBasket = exports.AuctionRound = void 0
|
|
7
7
|
const decimal_js_light_1 = __importDefault(require("decimal.js-light"));
|
8
8
|
const numbers_1 = require("./numbers");
|
9
9
|
const types_1 = require("./types");
|
10
|
-
|
10
|
+
// Create a local Decimal constructor with custom precision
|
11
|
+
const Decimal = decimal_js_light_1.default.clone({ precision: 100 });
|
11
12
|
// Call `getOpenAuction()` to get the current auction round
|
12
13
|
var AuctionRound;
|
13
14
|
(function (AuctionRound) {
|
@@ -31,10 +32,10 @@ const getTargetBasket = (_initialWeights, _prices, _decimals) => {
|
|
31
32
|
throw new Error("length mismatch");
|
32
33
|
}
|
33
34
|
const vals = _initialWeights.map((initialWeight, i) => {
|
34
|
-
const price = new
|
35
|
-
const decimalScale = new
|
35
|
+
const price = new Decimal(_prices[i]);
|
36
|
+
const decimalScale = new Decimal(`1e${_decimals[i]}`);
|
36
37
|
// {USD/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27 * {USD/wholeTok}
|
37
|
-
return new
|
38
|
+
return new Decimal(initialWeight.spot.toString()).div(decimalScale).mul(price).div(numbers_1.D9d);
|
38
39
|
});
|
39
40
|
const totalValue = vals.reduce((a, b) => a.add(b));
|
40
41
|
// D18{1} = {USD/wholeBU} / {USD/wholeBU} * D18
|
@@ -75,33 +76,33 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
|
|
75
76
|
}
|
76
77
|
// ================================================================
|
77
78
|
// {wholeShare} = {share} / {share/wholeShare}
|
78
|
-
const supply = new
|
79
|
+
const supply = new Decimal(_supply.toString()).div(numbers_1.D18d);
|
79
80
|
// {1} = D18{1} / D18
|
80
|
-
const targetBasket = _targetBasket.map((a) => new
|
81
|
+
const targetBasket = _targetBasket.map((a) => new Decimal(a.toString()).div(numbers_1.D18d));
|
81
82
|
// {USD/wholeTok}
|
82
|
-
const prices = _prices.map((a) => new
|
83
|
+
const prices = _prices.map((a) => new Decimal(a));
|
83
84
|
for (let i = 0; i < prices.length; i++) {
|
84
85
|
if (prices[i].eq(numbers_1.ZERO)) {
|
85
86
|
throw new Error(`missing price for token ${rebalance.tokens[i]}`);
|
86
87
|
}
|
87
88
|
}
|
88
89
|
// {1}
|
89
|
-
const priceError = _priceError.map((a) => new
|
90
|
+
const priceError = _priceError.map((a) => new Decimal(a.toString()));
|
90
91
|
// {tok/wholeTok}
|
91
|
-
const decimalScale = _decimals.map((a) => new
|
92
|
+
const decimalScale = _decimals.map((a) => new Decimal(`1e${a}`));
|
92
93
|
// {wholeTok/wholeShare} = D18{tok/share} * {share/wholeShare} / {tok/wholeTok} / D18
|
93
|
-
const initialFolio = _initialFolio.map((c, i) => new
|
94
|
+
const initialFolio = _initialFolio.map((c, i) => new Decimal(c.toString()).div(decimalScale[i]));
|
94
95
|
// {wholeTok/wholeShare} = D18{tok/share} * {share/wholeShare} / {tok/wholeTok} / D18
|
95
|
-
const folio = _folio.map((c, i) => new
|
96
|
+
const folio = _folio.map((c, i) => new Decimal(c.toString()).div(decimalScale[i]));
|
96
97
|
// {wholeTok/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27
|
97
98
|
let weightRanges = rebalance.weights.map((range, i) => {
|
98
99
|
return {
|
99
|
-
low: new
|
100
|
-
spot: new
|
101
|
-
high: new
|
100
|
+
low: new Decimal(range.low.toString()).div(decimalScale[i]).div(numbers_1.D9d),
|
101
|
+
spot: new Decimal(range.spot.toString()).div(decimalScale[i]).div(numbers_1.D9d),
|
102
|
+
high: new Decimal(range.high.toString()).div(decimalScale[i]).div(numbers_1.D9d),
|
102
103
|
};
|
103
104
|
});
|
104
|
-
const finalStageAt = new
|
105
|
+
const finalStageAt = new Decimal(_finalStageAt.toString());
|
105
106
|
// ================================================================
|
106
107
|
// calculate ideal spot limit, the actual BU<->share ratio
|
107
108
|
// {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
|
@@ -147,40 +148,38 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
|
|
147
148
|
.reduce((a, b) => a.add(b), numbers_1.ZERO)
|
148
149
|
.div(shareValue);
|
149
150
|
// ================================================================
|
150
|
-
// {wholeBU/wholeShare} = D18{BU/share} / D18
|
151
|
-
const prevSpotLimit = new decimal_js_light_1.default(rebalance.limits.spot.toString()).div(numbers_1.D18d);
|
152
151
|
// calculate progressions
|
153
|
-
// {
|
152
|
+
// {wholeBU/wholeShare} = D18{BU/share} / D18
|
153
|
+
const prevSpotLimit = new Decimal(rebalance.limits.spot.toString()).div(numbers_1.D18d);
|
154
|
+
// {wholeTok/wholeBU} = {wholeTok/wholeBU} * {wholeBU/wholeShare}
|
155
|
+
const expectedBalances = weightRanges.map((weightRange) => weightRange.spot.mul(prevSpotLimit));
|
156
|
+
// {1} = {USD/wholeShare} / {USD/wholeShare}
|
154
157
|
let progression = folio
|
155
158
|
.map((actualBalance, i) => {
|
156
159
|
if (!rebalance.inRebalance[i]) {
|
157
160
|
return numbers_1.ZERO;
|
158
161
|
}
|
159
|
-
// {wholeTok/
|
160
|
-
const
|
161
|
-
// {wholeTok/
|
162
|
-
const balanceInBasket = weightRanges[i].spot.gt(actualInBU) ? actualInBU : weightRanges[i].spot;
|
163
|
-
// {USD/wholeBU} = {wholeTok/wholeBU} * {USD/wholeTok}
|
162
|
+
// {wholeTok/wholeShare}
|
163
|
+
const balanceInBasket = expectedBalances[i].gt(actualBalance) ? actualBalance : expectedBalances[i];
|
164
|
+
// {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
|
164
165
|
return balanceInBasket.mul(prices[i]);
|
165
166
|
})
|
166
167
|
.reduce((a, b) => a.add(b))
|
167
|
-
.div(
|
168
|
-
// {1} = {USD/
|
168
|
+
.div(shareValue);
|
169
|
+
// {1} = {USD/wholeShare} / {USD/wholeShare}
|
169
170
|
const initialProgression = initialFolio
|
170
171
|
.map((initialBalance, i) => {
|
171
172
|
// make sure to include tokens that were already ejected
|
172
173
|
if (!rebalance.inRebalance[i] && rebalance.weights[i].spot > 0n) {
|
173
174
|
return numbers_1.ZERO;
|
174
175
|
}
|
175
|
-
// {wholeTok/
|
176
|
-
const
|
177
|
-
// {wholeTok/
|
178
|
-
const balanceInBasket = weightRanges[i].spot.gt(initialInBU) ? initialInBU : weightRanges[i].spot;
|
179
|
-
// {USD/wholeBU} = {wholeTok/wholeBU} * {USD/wholeTok}
|
176
|
+
// {wholeTok/wholeShare}
|
177
|
+
const balanceInBasket = expectedBalances[i].gt(initialBalance) ? initialBalance : expectedBalances[i];
|
178
|
+
// {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
|
180
179
|
return balanceInBasket.mul(prices[i]);
|
181
180
|
})
|
182
181
|
.reduce((a, b) => a.add(b))
|
183
|
-
.div(
|
182
|
+
.div(shareValue);
|
184
183
|
if (progression < initialProgression) {
|
185
184
|
progression = initialProgression; // don't go backwards
|
186
185
|
}
|
@@ -276,9 +275,9 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
|
|
276
275
|
// get new weights, constrained by extremes
|
277
276
|
// {wholeBU/wholeShare} = D18{BU/share} / D18
|
278
277
|
const actualLimits = {
|
279
|
-
low: new
|
280
|
-
spot: new
|
281
|
-
high: new
|
278
|
+
low: new Decimal(newLimits.low.toString()).div(numbers_1.D18d),
|
279
|
+
spot: new Decimal(newLimits.spot.toString()).div(numbers_1.D18d),
|
280
|
+
high: new Decimal(newLimits.high.toString()).div(numbers_1.D18d),
|
282
281
|
};
|
283
282
|
// D27{tok/BU}
|
284
283
|
const newWeights = rebalance.weights.map((weightRange, i) => {
|
@@ -370,9 +369,9 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
|
|
370
369
|
// {wholeTok/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27
|
371
370
|
weightRanges = newWeights.map((range, i) => {
|
372
371
|
return {
|
373
|
-
low: new
|
374
|
-
spot: new
|
375
|
-
high: new
|
372
|
+
low: new Decimal(range.low.toString()).div(decimalScale[i]).div(numbers_1.D9d),
|
373
|
+
spot: new Decimal(range.spot.toString()).div(decimalScale[i]).div(numbers_1.D9d),
|
374
|
+
high: new Decimal(range.high.toString()).div(decimalScale[i]).div(numbers_1.D9d),
|
376
375
|
};
|
377
376
|
});
|
378
377
|
// {USD}
|
package/dist/start-rebalance.js
CHANGED
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getStartRebalance = void 0;
|
7
7
|
const decimal_js_light_1 = __importDefault(require("decimal.js-light"));
|
8
8
|
const numbers_1 = require("./numbers");
|
9
|
+
// Create a local Decimal constructor with custom precision
|
10
|
+
const Decimal = decimal_js_light_1.default.clone({ precision: 100 });
|
9
11
|
/**
|
10
12
|
* Get the arguments needed to call startRebalance
|
11
13
|
*
|
@@ -26,19 +28,19 @@ const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _pr
|
|
26
28
|
console.log("getStartRebalance", _supply, tokens, _folio, decimals, _targetBasket, _prices, _priceError, weightControl);
|
27
29
|
}
|
28
30
|
// {wholeTok/wholeShare} = D18{tok/share} * {share/wholeShare} / {tok/wholeTok} / D18
|
29
|
-
const folio = _folio.map((c, i) => new
|
31
|
+
const folio = _folio.map((c, i) => new Decimal(c.toString()).div(new Decimal(`1e${decimals[i]}`)));
|
30
32
|
// convert price number inputs to bigints
|
31
33
|
// {USD/wholeTok}
|
32
|
-
const prices = _prices.map((a) => new
|
34
|
+
const prices = _prices.map((a) => new Decimal(a.toString()));
|
33
35
|
for (let i = 0; i < prices.length; i++) {
|
34
36
|
if (prices[i].eq(numbers_1.ZERO)) {
|
35
37
|
throw new Error(`missing price for token ${tokens[i]}`);
|
36
38
|
}
|
37
39
|
}
|
38
40
|
// {1} = D18{1} / D18
|
39
|
-
const targetBasket = _targetBasket.map((a) => new
|
41
|
+
const targetBasket = _targetBasket.map((a) => new Decimal(a.toString()).div(numbers_1.D18d));
|
40
42
|
// {1}
|
41
|
-
const priceError = _priceError.map((a) => new
|
43
|
+
const priceError = _priceError.map((a) => new Decimal(a.toString()));
|
42
44
|
// ================================================================
|
43
45
|
const newWeights = [];
|
44
46
|
const newPrices = [];
|
@@ -60,7 +62,7 @@ const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _pr
|
|
60
62
|
// {wholeTok/wholeShare} = {1} * {USD/wholeShare} / {USD/wholeTok}
|
61
63
|
const spotWeight = targetBasket[i].mul(dtfPrice).div(prices[i]);
|
62
64
|
// D27{tok/share}{wholeShare/wholeTok} = D27 * {tok/wholeTok} / {share/wholeShare}
|
63
|
-
const limitMultiplier = numbers_1.D27d.mul(new
|
65
|
+
const limitMultiplier = numbers_1.D27d.mul(new Decimal(`1e${decimals[i]}`)).div(numbers_1.D18d);
|
64
66
|
if (debug) {
|
65
67
|
console.log("limitMultiplier", limitMultiplier.toString());
|
66
68
|
}
|
@@ -86,7 +88,7 @@ const getStartRebalance = (_supply, tokens, _folio, decimals, _targetBasket, _pr
|
|
86
88
|
}
|
87
89
|
// === newPrices ===
|
88
90
|
// D27{wholeTok/tok} = D27 / {tok/wholeTok}
|
89
|
-
const priceMultiplier = numbers_1.D27d.div(new
|
91
|
+
const priceMultiplier = numbers_1.D27d.div(new Decimal(`1e${decimals[i]}`));
|
90
92
|
// {USD/wholeTok} = {USD/wholeTok} * {1}
|
91
93
|
const lowPrice = prices[i].mul(numbers_1.ONE.sub(priceError[i]));
|
92
94
|
const highPrice = prices[i].mul(numbers_1.ONE.add(priceError[i]));
|
package/dist/utils.js
CHANGED
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getBasketDistribution = void 0;
|
7
7
|
const decimal_js_light_1 = __importDefault(require("decimal.js-light"));
|
8
8
|
const numbers_1 = require("./numbers");
|
9
|
+
// Create a local Decimal constructor with custom precision
|
10
|
+
const Decimal = decimal_js_light_1.default.clone({ precision: 100 });
|
9
11
|
/**
|
10
12
|
* This function can be used to get a basket distribution EITHER from a set of historical basket weights
|
11
13
|
* or from a set of current balances. Make sure to use prices from the right time.
|
@@ -16,11 +18,11 @@ const numbers_1 = require("./numbers");
|
|
16
18
|
* @returns D18{1} Current basket, total will be around 1e18 but not exactly
|
17
19
|
*/
|
18
20
|
const getBasketDistribution = (_bals, _prices, decimals) => {
|
19
|
-
const decimalScale = decimals.map((d) => new
|
21
|
+
const decimalScale = decimals.map((d) => new Decimal(`1e${d}`));
|
20
22
|
// {wholeTok} = {tok} / {tok/wholeTok}
|
21
|
-
const bals = _bals.map((bal, i) => new
|
23
|
+
const bals = _bals.map((bal, i) => new Decimal(bal.toString()).div(decimalScale[i]));
|
22
24
|
// {USD/wholeTok} = {USD/wholeTok}
|
23
|
-
const prices = _prices.map((a) => new
|
25
|
+
const prices = _prices.map((a) => new Decimal(a.toString()));
|
24
26
|
// {USD} = {wholeTok} * {USD/wholeTok}
|
25
27
|
const totalValue = bals
|
26
28
|
.map((bal, i) => bal.mul(prices[i]))
|