@drift-labs/sdk 2.52.0-beta.10 → 2.52.0-beta.12
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/VERSION +1 -1
- package/lib/math/amm.js +13 -8
- package/lib/priorityFee/priorityFeeSubscriber.js +3 -3
- package/package.json +1 -1
- package/src/math/amm.ts +37 -27
- package/src/priorityFee/priorityFeeSubscriber.ts +3 -3
- package/tests/amm/test.ts +313 -18
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.52.0-beta.
|
|
1
|
+
2.52.0-beta.12
|
package/lib/math/amm.js
CHANGED
|
@@ -456,12 +456,11 @@ function calculateSpreadReserves(amm, oraclePriceData, now) {
|
|
|
456
456
|
}
|
|
457
457
|
const quoteAssetReserveDelta = amm.quoteAssetReserve.div(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(spreadFraction));
|
|
458
458
|
let quoteAssetReserve;
|
|
459
|
-
if ((
|
|
460
|
-
|
|
461
|
-
quoteAssetReserve = amm.quoteAssetReserve.add(quoteAssetReserveDelta);
|
|
459
|
+
if (quoteAssetReserveDelta.gte(numericConstants_1.ZERO)) {
|
|
460
|
+
quoteAssetReserve = amm.quoteAssetReserve.add(quoteAssetReserveDelta.abs());
|
|
462
461
|
}
|
|
463
462
|
else {
|
|
464
|
-
quoteAssetReserve = amm.quoteAssetReserve.sub(quoteAssetReserveDelta);
|
|
463
|
+
quoteAssetReserve = amm.quoteAssetReserve.sub(quoteAssetReserveDelta.abs());
|
|
465
464
|
}
|
|
466
465
|
const baseAssetReserve = amm.sqrtK.mul(amm.sqrtK).div(quoteAssetReserve);
|
|
467
466
|
return {
|
|
@@ -471,12 +470,18 @@ function calculateSpreadReserves(amm, oraclePriceData, now) {
|
|
|
471
470
|
}
|
|
472
471
|
const reservePrice = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
473
472
|
// always allow 10 bps of price offset, up to a fifth of the market's max_spread
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
473
|
+
let maxOffset = 0;
|
|
474
|
+
let referencePriceOffset = numericConstants_1.ZERO;
|
|
475
|
+
if (amm.curveUpdateIntensity > 100) {
|
|
476
|
+
maxOffset = Math.max(amm.maxSpread / 5, (numericConstants_1.PERCENTAGE_PRECISION.toNumber() / 10000) *
|
|
477
|
+
(amm.curveUpdateIntensity - 100));
|
|
478
|
+
const liquidityFraction = calculateInventoryLiquidityRatio(amm.baseAssetAmountWithAmm, amm.baseAssetReserve, amm.minBaseAssetReserve, amm.maxBaseAssetReserve);
|
|
479
|
+
const liquidityFractionSigned = liquidityFraction.mul((0, __1.sigNum)(amm.baseAssetAmountWithAmm.add(amm.baseAssetAmountWithUnsettledLp)));
|
|
480
|
+
referencePriceOffset = calculateReferencePriceOffset(reservePrice, amm.last24HAvgFundingRate, liquidityFractionSigned, amm.historicalOracleData.lastOraclePriceTwap5Min, amm.lastMarkPriceTwap5Min, amm.historicalOracleData.lastOraclePriceTwap, amm.lastMarkPriceTwap, maxOffset);
|
|
481
|
+
}
|
|
477
482
|
const [longSpread, shortSpread] = calculateSpread(amm, oraclePriceData, now, reservePrice);
|
|
478
483
|
const askReserves = calculateSpreadReserve(longSpread + referencePriceOffset.toNumber(), types_1.PositionDirection.LONG, amm);
|
|
479
|
-
const bidReserves = calculateSpreadReserve(shortSpread + referencePriceOffset.toNumber(), types_1.PositionDirection.SHORT, amm);
|
|
484
|
+
const bidReserves = calculateSpreadReserve(-shortSpread + referencePriceOffset.toNumber(), types_1.PositionDirection.SHORT, amm);
|
|
480
485
|
return [bidReserves, askReserves];
|
|
481
486
|
}
|
|
482
487
|
exports.calculateSpreadReserves = calculateSpreadReserves;
|
|
@@ -25,16 +25,16 @@ class PriorityFeeSubscriber {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
get avgPriorityFee() {
|
|
28
|
-
return this.lastAvgStrategyResult;
|
|
28
|
+
return Math.floor(this.lastAvgStrategyResult);
|
|
29
29
|
}
|
|
30
30
|
get maxPriorityFee() {
|
|
31
|
-
return this.lastMaxStrategyResult;
|
|
31
|
+
return Math.floor(this.lastMaxStrategyResult);
|
|
32
32
|
}
|
|
33
33
|
get customPriorityFee() {
|
|
34
34
|
if (!this.customStrategy) {
|
|
35
35
|
console.error('Custom strategy not set');
|
|
36
36
|
}
|
|
37
|
-
return this.lastCustomStrategyResult;
|
|
37
|
+
return Math.floor(this.lastCustomStrategyResult);
|
|
38
38
|
}
|
|
39
39
|
async subscribe() {
|
|
40
40
|
if (this.intervalId) {
|
package/package.json
CHANGED
package/src/math/amm.ts
CHANGED
|
@@ -863,13 +863,14 @@ export function calculateSpreadReserves(
|
|
|
863
863
|
);
|
|
864
864
|
|
|
865
865
|
let quoteAssetReserve;
|
|
866
|
-
if (
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
quoteAssetReserve = amm.quoteAssetReserve.add(quoteAssetReserveDelta);
|
|
866
|
+
if (quoteAssetReserveDelta.gte(ZERO)) {
|
|
867
|
+
quoteAssetReserve = amm.quoteAssetReserve.add(
|
|
868
|
+
quoteAssetReserveDelta.abs()
|
|
869
|
+
);
|
|
871
870
|
} else {
|
|
872
|
-
quoteAssetReserve = amm.quoteAssetReserve.sub(
|
|
871
|
+
quoteAssetReserve = amm.quoteAssetReserve.sub(
|
|
872
|
+
quoteAssetReserveDelta.abs()
|
|
873
|
+
);
|
|
873
874
|
}
|
|
874
875
|
|
|
875
876
|
const baseAssetReserve = amm.sqrtK.mul(amm.sqrtK).div(quoteAssetReserve);
|
|
@@ -886,26 +887,35 @@ export function calculateSpreadReserves(
|
|
|
886
887
|
);
|
|
887
888
|
|
|
888
889
|
// always allow 10 bps of price offset, up to a fifth of the market's max_spread
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
890
|
+
let maxOffset = 0;
|
|
891
|
+
let referencePriceOffset = ZERO;
|
|
892
|
+
if (amm.curveUpdateIntensity > 100) {
|
|
893
|
+
maxOffset = Math.max(
|
|
894
|
+
amm.maxSpread / 5,
|
|
895
|
+
(PERCENTAGE_PRECISION.toNumber() / 10000) *
|
|
896
|
+
(amm.curveUpdateIntensity - 100)
|
|
897
|
+
);
|
|
898
|
+
|
|
899
|
+
const liquidityFraction = calculateInventoryLiquidityRatio(
|
|
900
|
+
amm.baseAssetAmountWithAmm,
|
|
901
|
+
amm.baseAssetReserve,
|
|
902
|
+
amm.minBaseAssetReserve,
|
|
903
|
+
amm.maxBaseAssetReserve
|
|
904
|
+
);
|
|
905
|
+
const liquidityFractionSigned = liquidityFraction.mul(
|
|
906
|
+
sigNum(amm.baseAssetAmountWithAmm.add(amm.baseAssetAmountWithUnsettledLp))
|
|
907
|
+
);
|
|
908
|
+
referencePriceOffset = calculateReferencePriceOffset(
|
|
909
|
+
reservePrice,
|
|
910
|
+
amm.last24HAvgFundingRate,
|
|
911
|
+
liquidityFractionSigned,
|
|
912
|
+
amm.historicalOracleData.lastOraclePriceTwap5Min,
|
|
913
|
+
amm.lastMarkPriceTwap5Min,
|
|
914
|
+
amm.historicalOracleData.lastOraclePriceTwap,
|
|
915
|
+
amm.lastMarkPriceTwap,
|
|
916
|
+
maxOffset
|
|
917
|
+
);
|
|
918
|
+
}
|
|
909
919
|
|
|
910
920
|
const [longSpread, shortSpread] = calculateSpread(
|
|
911
921
|
amm,
|
|
@@ -920,7 +930,7 @@ export function calculateSpreadReserves(
|
|
|
920
930
|
amm
|
|
921
931
|
);
|
|
922
932
|
const bidReserves = calculateSpreadReserve(
|
|
923
|
-
shortSpread + referencePriceOffset.toNumber(),
|
|
933
|
+
-shortSpread + referencePriceOffset.toNumber(),
|
|
924
934
|
PositionDirection.SHORT,
|
|
925
935
|
amm
|
|
926
936
|
);
|
|
@@ -46,18 +46,18 @@ export class PriorityFeeSubscriber {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
public get avgPriorityFee(): number {
|
|
49
|
-
return this.lastAvgStrategyResult;
|
|
49
|
+
return Math.floor(this.lastAvgStrategyResult);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
public get maxPriorityFee(): number {
|
|
53
|
-
return this.lastMaxStrategyResult;
|
|
53
|
+
return Math.floor(this.lastMaxStrategyResult);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
public get customPriorityFee(): number {
|
|
57
57
|
if (!this.customStrategy) {
|
|
58
58
|
console.error('Custom strategy not set');
|
|
59
59
|
}
|
|
60
|
-
return this.lastCustomStrategyResult;
|
|
60
|
+
return Math.floor(this.lastCustomStrategyResult);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
public async subscribe(): Promise<void> {
|
package/tests/amm/test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
calculateSpread,
|
|
9
9
|
calculateSpreadBN,
|
|
10
10
|
ZERO,
|
|
11
|
+
sigNum,
|
|
11
12
|
ONE,
|
|
12
13
|
calculateLiveOracleStd,
|
|
13
14
|
calculateLiveOracleTwap,
|
|
@@ -465,7 +466,7 @@ describe('AMM Tests', () => {
|
|
|
465
466
|
|
|
466
467
|
mockAmm.baseAssetAmountWithAmm = new BN(0);
|
|
467
468
|
mockAmm.pegMultiplier = new BN(13.553 * PEG_PRECISION.toNumber());
|
|
468
|
-
mockAmm.ammJitIntensity =
|
|
469
|
+
mockAmm.ammJitIntensity = 200;
|
|
469
470
|
mockAmm.curveUpdateIntensity = 200;
|
|
470
471
|
mockAmm.baseSpread = 2500;
|
|
471
472
|
mockAmm.maxSpread = 25000;
|
|
@@ -521,13 +522,13 @@ describe('AMM Tests', () => {
|
|
|
521
522
|
console.log('amm.baseAssetReserve:', mockAmm.baseAssetReserve.toString());
|
|
522
523
|
assert(mockAmm.baseAssetReserve.eq(new BN('1000000000')));
|
|
523
524
|
const reserves2 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
524
|
-
console.log(reserves2[
|
|
525
|
-
console.log(reserves2[
|
|
525
|
+
console.log(reserves2[0].baseAssetReserve.toString());
|
|
526
|
+
console.log(reserves2[0].quoteAssetReserve.toString());
|
|
526
527
|
|
|
527
|
-
assert(reserves2[0].baseAssetReserve.eq(new BN('
|
|
528
|
-
assert(reserves2[0].quoteAssetReserve.eq(new BN('
|
|
529
|
-
assert(reserves2[1].baseAssetReserve.eq(new BN('
|
|
530
|
-
assert(reserves2[1].quoteAssetReserve.eq(new BN('
|
|
528
|
+
assert(reserves2[0].baseAssetReserve.eq(new BN('1005050504')));
|
|
529
|
+
assert(reserves2[0].quoteAssetReserve.eq(new BN('994974875')));
|
|
530
|
+
assert(reserves2[1].baseAssetReserve.eq(new BN('992537314')));
|
|
531
|
+
assert(reserves2[1].quoteAssetReserve.eq(new BN('1007518796')));
|
|
531
532
|
|
|
532
533
|
// create imbalance for reference price offset
|
|
533
534
|
mockAmm.baseAssetReserve = new BN(1000000000 * 1.1);
|
|
@@ -536,11 +537,12 @@ describe('AMM Tests', () => {
|
|
|
536
537
|
mockAmm.baseAssetReserve.mul(mockAmm.quoteAssetReserve)
|
|
537
538
|
);
|
|
538
539
|
|
|
539
|
-
mockAmm.baseAssetAmountWithAmm = new BN(
|
|
540
|
+
mockAmm.baseAssetAmountWithAmm = new BN(1000000000 * 0.1);
|
|
540
541
|
|
|
541
542
|
const maxOffset = Math.max(
|
|
542
543
|
mockAmm.maxSpread / 5,
|
|
543
|
-
PERCENTAGE_PRECISION.toNumber() /
|
|
544
|
+
(PERCENTAGE_PRECISION.toNumber() / 10000) *
|
|
545
|
+
(mockAmm.curveUpdateIntensity - 100)
|
|
544
546
|
);
|
|
545
547
|
const liquidityFraction = calculateInventoryLiquidityRatio(
|
|
546
548
|
mockAmm.baseAssetAmountWithAmm,
|
|
@@ -550,11 +552,17 @@ describe('AMM Tests', () => {
|
|
|
550
552
|
);
|
|
551
553
|
console.log('liquidityFraction:', liquidityFraction.toString());
|
|
552
554
|
assert(liquidityFraction.eq(new BN(1000000))); // full
|
|
553
|
-
|
|
555
|
+
const liquidityFractionSigned = liquidityFraction.mul(
|
|
556
|
+
sigNum(
|
|
557
|
+
mockAmm.baseAssetAmountWithAmm.add(
|
|
558
|
+
mockAmm.baseAssetAmountWithUnsettledLp
|
|
559
|
+
)
|
|
560
|
+
)
|
|
561
|
+
);
|
|
554
562
|
const referencePriceOffset = calculateReferencePriceOffset(
|
|
555
563
|
reservePrice,
|
|
556
564
|
mockAmm.last24HAvgFundingRate,
|
|
557
|
-
|
|
565
|
+
liquidityFractionSigned,
|
|
558
566
|
mockAmm.historicalOracleData.lastOraclePriceTwap5Min,
|
|
559
567
|
mockAmm.lastMarkPriceTwap5Min,
|
|
560
568
|
mockAmm.historicalOracleData.lastOraclePriceTwap,
|
|
@@ -562,17 +570,304 @@ describe('AMM Tests', () => {
|
|
|
562
570
|
maxOffset
|
|
563
571
|
);
|
|
564
572
|
console.log('referencePriceOffset:', referencePriceOffset.toString());
|
|
565
|
-
assert(referencePriceOffset.eq(new BN(
|
|
573
|
+
assert(referencePriceOffset.eq(new BN(10000)));
|
|
566
574
|
assert(referencePriceOffset.eq(new BN(maxOffset)));
|
|
567
575
|
|
|
576
|
+
// mockAmm.curveUpdateIntensity = 100;
|
|
577
|
+
const reserves3 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
578
|
+
console.log(reserves3[0].baseAssetReserve.toString());
|
|
579
|
+
console.log(reserves3[0].quoteAssetReserve.toString());
|
|
580
|
+
|
|
581
|
+
assert(reserves3[0].baseAssetReserve.eq(new BN('1094581278')));
|
|
582
|
+
assert(reserves3[0].quoteAssetReserve.eq(new BN('913591359')));
|
|
583
|
+
assert(reserves3[1].baseAssetReserve.eq(new BN('989999998')));
|
|
584
|
+
assert(reserves3[1].quoteAssetReserve.eq(new BN('1010101010')));
|
|
585
|
+
|
|
586
|
+
const p1 = calculatePrice(
|
|
587
|
+
reserves3[0].baseAssetReserve,
|
|
588
|
+
reserves3[0].quoteAssetReserve,
|
|
589
|
+
mockAmm.pegMultiplier
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
const p2 = calculatePrice(
|
|
593
|
+
reserves3[1].baseAssetReserve,
|
|
594
|
+
reserves3[1].quoteAssetReserve,
|
|
595
|
+
mockAmm.pegMultiplier
|
|
596
|
+
);
|
|
597
|
+
console.log(p1.toString(), p2.toString());
|
|
598
|
+
|
|
599
|
+
assert(p1.eq(new BN(11312000)));
|
|
600
|
+
assert(p2.eq(new BN(13828180)));
|
|
601
|
+
|
|
602
|
+
mockAmm.curveUpdateIntensity = 110;
|
|
603
|
+
const reserves4 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
604
|
+
console.log(reserves4[1].baseAssetReserve.toString());
|
|
605
|
+
console.log(reserves4[1].quoteAssetReserve.toString());
|
|
606
|
+
|
|
607
|
+
assert(reserves4[0].baseAssetReserve.eq(new BN('1097323599')));
|
|
608
|
+
assert(reserves4[0].quoteAssetReserve.eq(new BN('911308203')));
|
|
609
|
+
assert(reserves4[1].baseAssetReserve.eq(new BN('989999998')));
|
|
610
|
+
assert(reserves4[1].quoteAssetReserve.eq(new BN('1010101010')));
|
|
611
|
+
|
|
612
|
+
const p1RF = calculatePrice(
|
|
613
|
+
reserves4[0].baseAssetReserve,
|
|
614
|
+
reserves4[0].quoteAssetReserve,
|
|
615
|
+
mockAmm.pegMultiplier
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
const p2RF = calculatePrice(
|
|
619
|
+
reserves4[1].baseAssetReserve,
|
|
620
|
+
reserves4[1].quoteAssetReserve,
|
|
621
|
+
mockAmm.pegMultiplier
|
|
622
|
+
);
|
|
623
|
+
console.log(p1RF.toString(), p2RF.toString());
|
|
624
|
+
|
|
625
|
+
assert(p1RF.eq(new BN(11255531)));
|
|
626
|
+
assert(p2RF.eq(new BN(13828180)));
|
|
627
|
+
// no ref price offset at 100
|
|
628
|
+
mockAmm.curveUpdateIntensity = 100;
|
|
629
|
+
const reserves5 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
630
|
+
console.log(reserves5[0].baseAssetReserve.toString());
|
|
631
|
+
console.log(reserves5[0].quoteAssetReserve.toString());
|
|
632
|
+
|
|
633
|
+
assert(reserves5[0].baseAssetReserve.eq(new BN('1100068201')));
|
|
634
|
+
assert(reserves5[0].quoteAssetReserve.eq(new BN('909034546')));
|
|
635
|
+
assert(reserves5[1].baseAssetReserve.eq(new BN('989999998')));
|
|
636
|
+
assert(reserves5[1].quoteAssetReserve.eq(new BN('1010101010')));
|
|
637
|
+
|
|
638
|
+
const p1RFNone = calculatePrice(
|
|
639
|
+
reserves5[0].baseAssetReserve,
|
|
640
|
+
reserves5[0].quoteAssetReserve,
|
|
641
|
+
mockAmm.pegMultiplier
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
const p2RFNone = calculatePrice(
|
|
645
|
+
reserves5[1].baseAssetReserve,
|
|
646
|
+
reserves5[1].quoteAssetReserve,
|
|
647
|
+
mockAmm.pegMultiplier
|
|
648
|
+
);
|
|
649
|
+
console.log(p1RFNone.toString(), p2RFNone.toString());
|
|
650
|
+
|
|
651
|
+
assert(p1RFNone.eq(new BN(11199437)));
|
|
652
|
+
assert(p2RFNone.eq(new BN(13828180)));
|
|
653
|
+
assert(p1RF.sub(p1RFNone).eq(new BN(56094)));
|
|
654
|
+
assert(p2RF.sub(p2RFNone).eq(new BN(0))); // todo?
|
|
655
|
+
});
|
|
656
|
+
it('Spread Reserves (with negative offset)', () => {
|
|
657
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
658
|
+
const mockMarket1 = myMockPerpMarkets[0];
|
|
659
|
+
const mockAmm = mockMarket1.amm;
|
|
660
|
+
const now = new BN(new Date().getTime() / 1000); //todo
|
|
661
|
+
|
|
662
|
+
const oraclePriceData = {
|
|
663
|
+
price: new BN(13.553 * PRICE_PRECISION.toNumber()),
|
|
664
|
+
slot: new BN(68 + 1),
|
|
665
|
+
confidence: new BN(1),
|
|
666
|
+
hasSufficientNumberOfDataPoints: true,
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
const reserves = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
670
|
+
assert(reserves[0].baseAssetReserve.eq(new BN('1000000000')));
|
|
671
|
+
assert(reserves[0].quoteAssetReserve.eq(new BN('12000000000')));
|
|
672
|
+
assert(reserves[1].baseAssetReserve.eq(new BN('1000000000')));
|
|
673
|
+
assert(reserves[1].quoteAssetReserve.eq(new BN('12000000000')));
|
|
674
|
+
|
|
675
|
+
mockAmm.baseAssetReserve = new BN(1000000000);
|
|
676
|
+
mockAmm.quoteAssetReserve = new BN(1000000000);
|
|
677
|
+
mockAmm.sqrtK = new BN(1000000000);
|
|
678
|
+
|
|
679
|
+
mockAmm.baseAssetAmountWithAmm = new BN(0);
|
|
680
|
+
mockAmm.pegMultiplier = new BN(13.553 * PEG_PRECISION.toNumber());
|
|
681
|
+
mockAmm.ammJitIntensity = 200;
|
|
682
|
+
mockAmm.curveUpdateIntensity = 200;
|
|
683
|
+
mockAmm.baseSpread = 2500;
|
|
684
|
+
mockAmm.maxSpread = 25000;
|
|
685
|
+
|
|
686
|
+
mockAmm.last24HAvgFundingRate = new BN(-7590328523);
|
|
687
|
+
|
|
688
|
+
mockAmm.lastMarkPriceTwap = new BN(
|
|
689
|
+
(oraclePriceData.price.toNumber() / 1e6 + 0.01) * 1e6
|
|
690
|
+
);
|
|
691
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap = new BN(
|
|
692
|
+
(oraclePriceData.price.toNumber() / 1e6 - 0.015) * 1e6
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap5Min = new BN(
|
|
696
|
+
(oraclePriceData.price.toNumber() / 1e6 + 0.005) * 1e6
|
|
697
|
+
);
|
|
698
|
+
mockAmm.lastMarkPriceTwap5Min = new BN(
|
|
699
|
+
(oraclePriceData.price.toNumber() / 1e6 - 0.005) * 1e6
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
console.log('starting rr:');
|
|
703
|
+
let reservePrice = undefined;
|
|
704
|
+
if (!reservePrice) {
|
|
705
|
+
reservePrice = calculatePrice(
|
|
706
|
+
mockAmm.baseAssetReserve,
|
|
707
|
+
mockAmm.quoteAssetReserve,
|
|
708
|
+
mockAmm.pegMultiplier
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const targetPrice = oraclePriceData?.price || reservePrice;
|
|
713
|
+
const confInterval = oraclePriceData.confidence || ZERO;
|
|
714
|
+
const targetMarkSpreadPct = reservePrice
|
|
715
|
+
.sub(targetPrice)
|
|
716
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
717
|
+
.div(reservePrice);
|
|
718
|
+
|
|
719
|
+
const confIntervalPct = confInterval
|
|
720
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
721
|
+
.div(reservePrice);
|
|
722
|
+
|
|
723
|
+
// now = now || new BN(new Date().getTime() / 1000); //todo
|
|
724
|
+
const liveOracleStd = calculateLiveOracleStd(mockAmm, oraclePriceData, now);
|
|
725
|
+
console.log('reservePrice:', reservePrice.toString());
|
|
726
|
+
console.log('targetMarkSpreadPct:', targetMarkSpreadPct.toString());
|
|
727
|
+
console.log('confIntervalPct:', confIntervalPct.toString());
|
|
728
|
+
|
|
729
|
+
console.log('liveOracleStd:', liveOracleStd.toString());
|
|
730
|
+
|
|
731
|
+
const tt = calculateSpread(mockAmm, oraclePriceData, now);
|
|
732
|
+
console.log(tt);
|
|
733
|
+
|
|
734
|
+
console.log('amm.baseAssetReserve:', mockAmm.baseAssetReserve.toString());
|
|
735
|
+
assert(mockAmm.baseAssetReserve.eq(new BN('1000000000')));
|
|
736
|
+
const reserves2 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
737
|
+
console.log(reserves2[1].baseAssetReserve.toString());
|
|
738
|
+
console.log(reserves2[1].quoteAssetReserve.toString());
|
|
739
|
+
|
|
740
|
+
assert(reserves2[0].baseAssetReserve.eq(new BN('1006289308')));
|
|
741
|
+
assert(reserves2[0].quoteAssetReserve.eq(new BN('993750000')));
|
|
742
|
+
assert(reserves2[1].baseAssetReserve.eq(new BN('993788819')));
|
|
743
|
+
assert(reserves2[1].quoteAssetReserve.eq(new BN('1006250000')));
|
|
744
|
+
|
|
745
|
+
// create imbalance for reference price offset
|
|
746
|
+
mockAmm.baseAssetReserve = new BN(1000000000 / 1.1);
|
|
747
|
+
mockAmm.quoteAssetReserve = new BN(1000000000 * 1.1);
|
|
748
|
+
mockAmm.sqrtK = squareRootBN(
|
|
749
|
+
mockAmm.baseAssetReserve.mul(mockAmm.quoteAssetReserve)
|
|
750
|
+
);
|
|
751
|
+
|
|
752
|
+
mockAmm.baseAssetAmountWithAmm = new BN(-1000000000 * 0.1);
|
|
753
|
+
|
|
754
|
+
const maxOffset = Math.max(
|
|
755
|
+
mockAmm.maxSpread / 5,
|
|
756
|
+
(PERCENTAGE_PRECISION.toNumber() / 10000) *
|
|
757
|
+
(mockAmm.curveUpdateIntensity - 100)
|
|
758
|
+
);
|
|
759
|
+
const liquidityFraction = calculateInventoryLiquidityRatio(
|
|
760
|
+
mockAmm.baseAssetAmountWithAmm,
|
|
761
|
+
mockAmm.baseAssetReserve,
|
|
762
|
+
mockAmm.minBaseAssetReserve,
|
|
763
|
+
mockAmm.maxBaseAssetReserve
|
|
764
|
+
);
|
|
765
|
+
console.log('liquidityFraction:', liquidityFraction.toString());
|
|
766
|
+
assert(liquidityFraction.eq(new BN(1000000))); // full
|
|
767
|
+
const liquidityFractionSigned = liquidityFraction.mul(
|
|
768
|
+
sigNum(
|
|
769
|
+
mockAmm.baseAssetAmountWithAmm.add(
|
|
770
|
+
mockAmm.baseAssetAmountWithUnsettledLp
|
|
771
|
+
)
|
|
772
|
+
)
|
|
773
|
+
);
|
|
774
|
+
const referencePriceOffset = calculateReferencePriceOffset(
|
|
775
|
+
reservePrice,
|
|
776
|
+
mockAmm.last24HAvgFundingRate,
|
|
777
|
+
liquidityFractionSigned,
|
|
778
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap5Min,
|
|
779
|
+
mockAmm.lastMarkPriceTwap5Min,
|
|
780
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap,
|
|
781
|
+
mockAmm.lastMarkPriceTwap,
|
|
782
|
+
maxOffset
|
|
783
|
+
);
|
|
784
|
+
console.log('referencePriceOffset:', referencePriceOffset.toString());
|
|
785
|
+
assert(referencePriceOffset.eq(new BN(-10000))); // neg
|
|
786
|
+
|
|
787
|
+
// assert(referencePriceOffset.eq(new BN(maxOffset)));
|
|
788
|
+
|
|
789
|
+
// mockAmm.curveUpdateIntensity = 100;
|
|
568
790
|
const reserves3 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
569
|
-
console.log(reserves3[
|
|
570
|
-
console.log(reserves3[
|
|
791
|
+
console.log(reserves3[0].baseAssetReserve.toString());
|
|
792
|
+
console.log(reserves3[0].quoteAssetReserve.toString());
|
|
793
|
+
|
|
794
|
+
assert(reserves3[0].baseAssetReserve.eq(new BN('1010101008')));
|
|
795
|
+
assert(reserves3[0].quoteAssetReserve.eq(new BN('990000000')));
|
|
796
|
+
assert(reserves3[1].baseAssetReserve.eq(new BN('913613747')));
|
|
797
|
+
assert(reserves3[1].quoteAssetReserve.eq(new BN('1094554456')));
|
|
798
|
+
|
|
799
|
+
const p1 = calculatePrice(
|
|
800
|
+
reserves3[0].baseAssetReserve,
|
|
801
|
+
reserves3[0].quoteAssetReserve,
|
|
802
|
+
mockAmm.pegMultiplier
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
const p2 = calculatePrice(
|
|
806
|
+
reserves3[1].baseAssetReserve,
|
|
807
|
+
reserves3[1].quoteAssetReserve,
|
|
808
|
+
mockAmm.pegMultiplier
|
|
809
|
+
);
|
|
810
|
+
console.log(p1.toString(), p2.toString());
|
|
811
|
+
|
|
812
|
+
assert(p1.eq(new BN(13283295)));
|
|
813
|
+
assert(p2.eq(new BN(16237164)));
|
|
814
|
+
|
|
815
|
+
mockAmm.curveUpdateIntensity = 110;
|
|
816
|
+
const reserves4 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
817
|
+
console.log(reserves4[1].baseAssetReserve.toString());
|
|
818
|
+
console.log(reserves4[1].quoteAssetReserve.toString());
|
|
819
|
+
|
|
820
|
+
assert(reserves4[0].baseAssetReserve.eq(new BN('999999998')));
|
|
821
|
+
assert(reserves4[0].quoteAssetReserve.eq(new BN('1000000000')));
|
|
822
|
+
assert(reserves4[1].baseAssetReserve.eq(new BN('911313622')));
|
|
823
|
+
assert(reserves4[1].quoteAssetReserve.eq(new BN('1097317074')));
|
|
824
|
+
|
|
825
|
+
const p1RF = calculatePrice(
|
|
826
|
+
reserves4[0].baseAssetReserve,
|
|
827
|
+
reserves4[0].quoteAssetReserve,
|
|
828
|
+
mockAmm.pegMultiplier
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
const p2RF = calculatePrice(
|
|
832
|
+
reserves4[1].baseAssetReserve,
|
|
833
|
+
reserves4[1].quoteAssetReserve,
|
|
834
|
+
mockAmm.pegMultiplier
|
|
835
|
+
);
|
|
836
|
+
console.log(p1RF.toString(), p2RF.toString());
|
|
837
|
+
|
|
838
|
+
assert(p1RF.eq(new BN(13553000)));
|
|
839
|
+
assert(p2RF.eq(new BN(16319231)));
|
|
840
|
+
|
|
841
|
+
// no ref price offset at 100
|
|
842
|
+
mockAmm.curveUpdateIntensity = 100;
|
|
843
|
+
const reserves5 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
844
|
+
console.log(reserves5[0].baseAssetReserve.toString());
|
|
845
|
+
console.log(reserves5[0].quoteAssetReserve.toString());
|
|
846
|
+
|
|
847
|
+
assert(reserves5[0].baseAssetReserve.eq(new BN('999999998')));
|
|
848
|
+
assert(reserves5[0].quoteAssetReserve.eq(new BN('1000000000')));
|
|
849
|
+
assert(reserves5[1].baseAssetReserve.eq(new BN('909034547')));
|
|
850
|
+
assert(reserves5[1].quoteAssetReserve.eq(new BN('1100068200')));
|
|
851
|
+
|
|
852
|
+
const p1RFNone = calculatePrice(
|
|
853
|
+
reserves5[0].baseAssetReserve,
|
|
854
|
+
reserves5[0].quoteAssetReserve,
|
|
855
|
+
mockAmm.pegMultiplier
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
const p2RFNone = calculatePrice(
|
|
859
|
+
reserves5[1].baseAssetReserve,
|
|
860
|
+
reserves5[1].quoteAssetReserve,
|
|
861
|
+
mockAmm.pegMultiplier
|
|
862
|
+
);
|
|
863
|
+
console.log(p1RFNone.toString(), p2RFNone.toString());
|
|
571
864
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
assert(
|
|
575
|
-
assert(
|
|
865
|
+
const rr = p2RF.sub(p2RFNone).mul(PERCENTAGE_PRECISION).div(p2RF);
|
|
866
|
+
console.log(rr.toNumber());
|
|
867
|
+
assert(p1RFNone.eq(new BN(13553000)));
|
|
868
|
+
assert(p2RFNone.eq(new BN(16401163)));
|
|
869
|
+
assert(p1RF.sub(p1RFNone).eq(new BN(0))); // todo?
|
|
870
|
+
assert(rr.eq(new BN(-5020)));
|
|
576
871
|
});
|
|
577
872
|
|
|
578
873
|
it('live update functions', () => {
|