@reserve-protocol/dtf-rebalance-lib 0.1.2 → 0.1.3

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.
@@ -1,4 +1,4 @@
1
- import { PriceRange, Rebalance, RebalanceLimits, WeightRange } from './types';
1
+ import { PriceRange, Rebalance, RebalanceLimits, WeightRange } from "./types";
2
2
  export declare enum AuctionRound {
3
3
  EJECT = 0,
4
4
  PROGRESS = 1,
@@ -27,17 +27,13 @@ var AuctionRound;
27
27
  */
28
28
  const getTargetBasket = (_initialWeights, _prices, _decimals) => {
29
29
  if (_initialWeights.length != _prices.length) {
30
- throw new Error('length mismatch');
30
+ throw new Error("length mismatch");
31
31
  }
32
32
  const vals = _initialWeights.map((initialWeight, i) => {
33
33
  const price = new decimal_js_light_1.default(_prices[i]);
34
34
  const decimalScale = new decimal_js_light_1.default(`1e${_decimals[i]}`);
35
35
  // {USD/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27 * {USD/wholeTok}
36
- return new decimal_js_light_1.default(initialWeight.spot.toString())
37
- .mul(numbers_1.D18d)
38
- .div(decimalScale)
39
- .div(numbers_1.D27d)
40
- .mul(price);
36
+ return new decimal_js_light_1.default(initialWeight.spot.toString()).mul(numbers_1.D18d).div(decimalScale).div(numbers_1.D27d).mul(price);
41
37
  });
42
38
  const totalValue = vals.reduce((a, b) => a.add(b));
43
39
  // D18{1} = {USD/wholeBU} / {USD/wholeBU} * D18
@@ -61,17 +57,17 @@ exports.getTargetBasket = getTargetBasket;
61
57
  */
62
58
  const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket = [], _folio, _decimals, _prices, _priceError, _finalStageAt, logging) => {
63
59
  if (logging) {
64
- console.log('getOpenAuction', rebalance, _supply, _initialFolio, _targetBasket, _folio, _decimals, _prices, _priceError, _finalStageAt);
60
+ console.log("getOpenAuction", rebalance, _supply, _initialFolio, _targetBasket, _folio, _decimals, _prices, _priceError, _finalStageAt);
65
61
  }
66
62
  if (rebalance.tokens.length != _targetBasket.length ||
67
63
  _targetBasket.length != _folio.length ||
68
64
  _folio.length != _decimals.length ||
69
65
  _decimals.length != _prices.length ||
70
66
  _prices.length != _priceError.length) {
71
- throw new Error('length mismatch');
67
+ throw new Error("length mismatch");
72
68
  }
73
69
  if (_finalStageAt > 1) {
74
- throw new Error('finalStageAt must be less than 1');
70
+ throw new Error("finalStageAt must be less than 1");
75
71
  }
76
72
  // ================================================================
77
73
  // {wholeShare} = {share} / {share/wholeShare}
@@ -96,34 +92,21 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
96
92
  // {wholeTok/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27
97
93
  let weightRanges = rebalance.weights.map((range, i) => {
98
94
  return {
99
- low: new decimal_js_light_1.default(range.low.toString())
100
- .mul(numbers_1.D18d)
101
- .div(decimalScale[i])
102
- .div(numbers_1.D27d),
103
- spot: new decimal_js_light_1.default(range.spot.toString())
104
- .mul(numbers_1.D18d)
105
- .div(decimalScale[i])
106
- .div(numbers_1.D27d),
107
- high: new decimal_js_light_1.default(range.high.toString())
108
- .mul(numbers_1.D18d)
109
- .div(decimalScale[i])
110
- .div(numbers_1.D27d),
95
+ low: new decimal_js_light_1.default(range.low.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
96
+ spot: new decimal_js_light_1.default(range.spot.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
97
+ high: new decimal_js_light_1.default(range.high.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
111
98
  };
112
99
  });
113
100
  const finalStageAt = new decimal_js_light_1.default(_finalStageAt.toString());
114
101
  // ================================================================
115
102
  // calculate ideal spot limit, the actual BU<->share ratio
116
103
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
117
- const shareValue = folio
118
- .map((f, i) => f.mul(prices[i]))
119
- .reduce((a, b) => a.add(b));
104
+ const shareValue = folio.map((f, i) => f.mul(prices[i])).reduce((a, b) => a.add(b));
120
105
  // {USD/wholeBU} = {wholeTok/wholeBU} * {USD/wholeTok}
121
- const buValue = weightRanges
122
- .map((weightRange, i) => weightRange.spot.mul(prices[i]))
123
- .reduce((a, b) => a.add(b));
106
+ const buValue = weightRanges.map((weightRange, i) => weightRange.spot.mul(prices[i])).reduce((a, b) => a.add(b));
124
107
  if (logging) {
125
- console.log('shareValue', shareValue.toString());
126
- console.log('buValue', buValue.toString());
108
+ console.log("shareValue", shareValue.toString());
109
+ console.log("buValue", buValue.toString());
127
110
  }
128
111
  // ================================================================
129
112
  // calculate rebalanceTarget
@@ -144,9 +127,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
144
127
  // {wholeTok/wholeShare} = {USD/wholeShare} * {1} / {USD/wholeTok}
145
128
  const balanceExpected = shareValue.mul(targetBasket[i]).div(prices[i]);
146
129
  // {wholeTok/wholeShare} = {wholeTok/wholeBU} * {wholeBU/wholeShare}
147
- const balanceInBU = balanceExpected.gt(actualBalance)
148
- ? actualBalance
149
- : balanceExpected;
130
+ const balanceInBU = balanceExpected.gt(actualBalance) ? actualBalance : balanceExpected;
150
131
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
151
132
  return balanceInBU.mul(prices[i]);
152
133
  })
@@ -158,9 +139,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
158
139
  // {wholeTok/wholeShare} = {USD/wholeShare} * {1} / {USD/wholeTok}
159
140
  const balanceExpected = shareValue.mul(targetBasket[i]).div(prices[i]);
160
141
  // {wholeTok/wholeShare} = {wholeTok/wholeBU} * {wholeBU/wholeShare}
161
- const balanceInBU = balanceExpected.gt(initialBalance)
162
- ? initialBalance
163
- : balanceExpected;
142
+ const balanceInBU = balanceExpected.gt(initialBalance) ? initialBalance : balanceExpected;
164
143
  // {USD/wholeShare} = {wholeTok/wholeShare} * {USD/wholeTok}
165
144
  return balanceInBU.mul(prices[i]);
166
145
  })
@@ -176,11 +155,11 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
176
155
  let rebalanceTarget = numbers_1.ONE;
177
156
  let round = AuctionRound.FINAL;
178
157
  if (logging) {
179
- console.log('initialProgression', initialProgression.toString());
180
- console.log('progression', progression.toString());
181
- console.log('relativeProgression', relativeProgression.toString());
182
- console.log('portionBeingEjected', portionBeingEjected.toString());
183
- console.log('finalStageAt', finalStageAt.toString());
158
+ console.log("initialProgression", initialProgression.toString());
159
+ console.log("progression", progression.toString());
160
+ console.log("relativeProgression", relativeProgression.toString());
161
+ console.log("portionBeingEjected", portionBeingEjected.toString());
162
+ console.log("finalStageAt", finalStageAt.toString());
184
163
  }
185
164
  // make it an eject auction if there is 1 bps or more of value to eject
186
165
  if (portionBeingEjected.gte(1e-4)) {
@@ -202,13 +181,13 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
202
181
  }
203
182
  }
204
183
  if (rebalanceTarget.gt(numbers_1.ONE)) {
205
- throw new Error('something has gone very wrong');
184
+ throw new Error("something has gone very wrong");
206
185
  }
207
- if (rebalanceTarget.lt(progression)) {
186
+ if (rebalanceTarget.lt(progression) || numbers_1.ONE.sub(rebalanceTarget).lt(1e-4)) {
208
187
  rebalanceTarget = numbers_1.ONE;
209
188
  }
210
189
  if (logging) {
211
- console.log('rebalanceTarget', rebalanceTarget.toString());
190
+ console.log("rebalanceTarget", rebalanceTarget.toString());
212
191
  }
213
192
  // {1}
214
193
  const delta = numbers_1.ONE.sub(rebalanceTarget);
@@ -224,9 +203,9 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
224
203
  };
225
204
  if (round == AuctionRound.EJECT && rebalanceTarget.eq(numbers_1.ONE)) {
226
205
  // aim 1% higher if executed permissonlessly
227
- newLimits.spot += newLimits.spot * 1n / 100n;
206
+ newLimits.spot += (newLimits.spot * 1n) / 100n;
228
207
  // leave 10% room to increase low in the future if ejection leaves dust behind
229
- newLimits.high += newLimits.high * 10n / 100n;
208
+ newLimits.high += (newLimits.high * 10n) / 100n;
230
209
  }
231
210
  // low
232
211
  if (newLimits.low < rebalance.limits.low) {
@@ -250,7 +229,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
250
229
  newLimits.high = rebalance.limits.high;
251
230
  }
252
231
  if (logging) {
253
- console.log('newLimits', newLimits);
232
+ console.log("newLimits", newLimits);
254
233
  }
255
234
  // ================================================================
256
235
  // get new weights, constrained by extremes
@@ -263,10 +242,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
263
242
  // D27{tok/BU}
264
243
  const newWeights = rebalance.weights.map((weightRange, i) => {
265
244
  // {wholeTok/wholeBU} = {USD/wholeShare} * {1} / {wholeBU/wholeShare} / {USD/wholeTok}
266
- const idealWeight = shareValue
267
- .mul(targetBasket[i])
268
- .div(actualLimits.spot)
269
- .div(prices[i]);
245
+ const idealWeight = shareValue.mul(targetBasket[i]).div(actualLimits.spot).div(prices[i]);
270
246
  // D27{tok/BU} = {wholeTok/wholeBU} * D27 * {tok/wholeTok} / {BU/wholeBU}
271
247
  const newWeightsD27 = {
272
248
  low: (0, numbers_1.bn)(idealWeight
@@ -283,9 +259,9 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
283
259
  };
284
260
  if (round == AuctionRound.EJECT && rebalanceTarget.eq(numbers_1.ONE)) {
285
261
  // aim 1% higher if executed permissonlessly
286
- newWeightsD27.spot += newWeightsD27.spot * 1n / 100n;
262
+ newWeightsD27.spot += (newWeightsD27.spot * 1n) / 100n;
287
263
  // leave 10% room to increase low in the future if ejection leaves dust behind
288
- newWeightsD27.high += newWeightsD27.high * 10n / 100n;
264
+ newWeightsD27.high += (newWeightsD27.high * 10n) / 100n;
289
265
  }
290
266
  if (newWeightsD27.low < weightRange.low) {
291
267
  newWeightsD27.low = weightRange.low;
@@ -308,7 +284,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
308
284
  return newWeightsD27;
309
285
  });
310
286
  if (logging) {
311
- console.log('newWeights', newWeights);
287
+ console.log("newWeights", newWeights);
312
288
  }
313
289
  // ================================================================
314
290
  // get new prices, constrained by extremes
@@ -317,7 +293,7 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
317
293
  // revert if price out of bounds
318
294
  const spotPrice = (0, numbers_1.bn)(prices[i].mul(numbers_1.D27d).div(decimalScale[i]));
319
295
  if (spotPrice < initialPrice.low || spotPrice > initialPrice.high) {
320
- throw new Error('spot price out of bounds! auction launcher MUST closeRebalance to prevent loss!');
296
+ throw new Error("spot price out of bounds! auction launcher MUST closeRebalance to prevent loss!");
321
297
  }
322
298
  if (rebalance.priceControl == types_1.PriceControl.NONE) {
323
299
  return initialPrice;
@@ -342,38 +318,26 @@ const getOpenAuction = (rebalance, _supply, _initialFolio = [], _targetBasket =
342
318
  pricesD27.high = initialPrice.high;
343
319
  }
344
320
  if (pricesD27.low == pricesD27.high && priceError[i].gt(numbers_1.ZERO)) {
345
- throw new Error('no price range');
321
+ throw new Error("no price range");
346
322
  }
347
323
  return pricesD27;
348
324
  });
349
325
  if (logging) {
350
- console.log('newPrices', newPrices);
326
+ console.log("newPrices", newPrices);
351
327
  }
352
328
  // ================================================================
353
329
  // calculate metrics
354
330
  // {USD} = {1} * {USD/wholeShare} * {wholeShare}
355
- const valueBeingTraded = rebalanceTarget
356
- .sub(progression)
357
- .mul(shareValue)
358
- .mul(supply);
331
+ const valueBeingTraded = rebalanceTarget.sub(progression).mul(shareValue).mul(supply);
359
332
  const surplusTokens = [];
360
333
  const deficitTokens = [];
361
334
  // update Decimal weightRanges
362
335
  // {wholeTok/wholeBU} = D27{tok/BU} * {BU/wholeBU} / {tok/wholeTok} / D27
363
336
  weightRanges = newWeights.map((range, i) => {
364
337
  return {
365
- low: new decimal_js_light_1.default(range.low.toString())
366
- .mul(numbers_1.D18d)
367
- .div(decimalScale[i])
368
- .div(numbers_1.D27d),
369
- spot: new decimal_js_light_1.default(range.spot.toString())
370
- .mul(numbers_1.D18d)
371
- .div(decimalScale[i])
372
- .div(numbers_1.D27d),
373
- high: new decimal_js_light_1.default(range.high.toString())
374
- .mul(numbers_1.D18d)
375
- .div(decimalScale[i])
376
- .div(numbers_1.D27d),
338
+ low: new decimal_js_light_1.default(range.low.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
339
+ spot: new decimal_js_light_1.default(range.spot.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
340
+ high: new decimal_js_light_1.default(range.high.toString()).mul(numbers_1.D18d).div(decimalScale[i]).div(numbers_1.D27d),
377
341
  };
378
342
  });
379
343
  rebalance.tokens.forEach((token, i) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reserve-protocol/dtf-rebalance-lib",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Rebalancing library for DTFs in typescript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "prepublishOnly": "npm run build",
18
18
  "test": "npm run test:unit && npm run test:e2e",
19
19
  "test:unit": "node --test --require ts-node/register test/unit/*.test.ts",
20
- "test:e2e": "hardhat test --bail"
20
+ "test:e2e": "hardhat test test/e2e/*.test.ts --bail"
21
21
  },
22
22
  "publishConfig": {
23
23
  "access": "public"