@d8x/perpetuals-sdk 2.1.2-alpha2 → 2.1.4-alpha2

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/src/d8XMath.ts CHANGED
@@ -528,7 +528,7 @@ export function expectedLoss(
528
528
  ds = Math.abs(tradeAmt);
529
529
  }
530
530
  const a = Math.max(0, dl + totLong - m * totShort - dsm);
531
- const b = Math.max(0, ds + totShort - m * totLong + dsm);
531
+ const b = Math.max(0, ds + totShort - m * totLong - dlm);
532
532
  return p * (1 - p) * (a + b);
533
533
  }
534
534
 
@@ -649,9 +649,241 @@ function excessMargin(
649
649
  return b0 / S3 - thresh / S3 - fee_cc;
650
650
  }
651
651
 
652
+ /**
653
+ * Internal function to find the deposit amount required
654
+ * for a given trade amount and target leverage
655
+ * @param tradeAmt
656
+ * @param targetLvg
657
+ * @param price
658
+ * @param S3
659
+ * @param S2Mark
660
+ * @returns
661
+ */
662
+ function pmGetDepositAmtForLvgTrade(
663
+ tradeAmt: number,
664
+ targetLvg: number,
665
+ price: number,
666
+ S3: number,
667
+ S2Mark: number
668
+ ): number {
669
+ const pnl = (tradeAmt * (S2Mark - price)) / S3;
670
+ let p = S2Mark - 1;
671
+ if (tradeAmt < 0) {
672
+ p = 1 - p;
673
+ }
674
+ const b = (Math.abs(tradeAmt) * p) / S3 / targetLvg;
675
+ const amt = -(pnl - b);
676
+ // check:
677
+ //bal = amt+pnl
678
+ //pos_val = (np.abs(trade_amt) * p) / S3
679
+ //lvg = pos_val/bal
680
+ //assert(np.abs(lvg-targetLvg)<0.1)
681
+ return amt;
682
+ }
683
+
684
+ /**
685
+ * Internal function to calculate cash over initial margin rate
686
+ * after a trade of size tradeAmt in prediction markets
687
+ * @param tradeAmt
688
+ * @param lvg
689
+ * @param walletBalCC
690
+ * @param currentCashCC
691
+ * @param currentPosition
692
+ * @param currentLockedInValue
693
+ * @param slippage
694
+ * @param S2
695
+ * @param Sm
696
+ * @param S3
697
+ * @param totLong
698
+ * @param totShort
699
+ * @returns
700
+ */
701
+ function pmExcessCashAtLvg(
702
+ tradeAmt: number,
703
+ lvg: number,
704
+ walletBalCC: number,
705
+ currentCashCC: number,
706
+ currentPosition: number,
707
+ currentLockedInValue: number,
708
+ slippage: number,
709
+ S2: number,
710
+ Sm: number,
711
+ S3: number,
712
+ totLong: number,
713
+ totShort: number
714
+ ): number {
715
+ //determine deposit amount for given leverage
716
+ const limitPrice = S2 * (1 + Math.sign(tradeAmt) * slippage);
717
+ const depositFromWallet = pmGetDepositAmtForLvgTrade(tradeAmt, lvg, limitPrice, S3, Sm);
718
+ const m0 = 0.18;
719
+ //leverage fee
720
+ let p0 = Sm - 1;
721
+ if (tradeAmt < 0) {
722
+ p0 = 2 - Sm; //=1-(Sm-1)
723
+ }
724
+ const feeCc = pmExchangeFee(p0, m0, totShort, totLong, tradeAmt, 1 / lvg) / S3;
725
+
726
+ //excess cash
727
+ let exc = walletBalCC - depositFromWallet - feeCc;
728
+
729
+ // margin balance
730
+ let pos = currentPosition + tradeAmt;
731
+ let p = Sm - 1;
732
+ if (pos < 0) {
733
+ p = 2 - Sm;
734
+ }
735
+ const h = entropy(p);
736
+ const tau = m0 + (0.5 - m0) * h;
737
+ const thresh = Math.abs(pos) * p * tau;
738
+ const b0 =
739
+ depositFromWallet +
740
+ currentCashCC +
741
+ Math.abs(currentPosition) * Sm -
742
+ currentLockedInValue +
743
+ Math.max(0, tradeAmt * (Sm - limitPrice));
744
+ // b0 - fee > threshold
745
+ // b0 - fee - threshold > 0
746
+ // extra_cash = b0 - fee - threshold
747
+ // missing: referral rebate
748
+ const bal = b0 / S3 - thresh / S3 - feeCc;
749
+ exc = exc + bal;
750
+ return exc;
751
+ }
752
+
753
+ /**
754
+ * Find maximal trade size (short dir=-1 or long dir=1) for prediction
755
+ * markets at provided leverage and incorporating the current position
756
+ * and wallet balance.
757
+ * Factors in lot size and global max short/long
758
+ * @param dir
759
+ * @param lvg
760
+ * @param walletBalCC
761
+ * @param slippage slippage percent
762
+ * @param currentPosition
763
+ * @param currentCashCC
764
+ * @param currentLockedInValue
765
+ * @param S2
766
+ * @param Sm
767
+ * @param S3
768
+ * @param totLong
769
+ * @param totShort
770
+ * @param maxShort
771
+ * @param maxLong
772
+ * @returns
773
+ */
774
+ export function pmFindMaxPersonalTradeSizeAtLeverage(
775
+ dir: number,
776
+ lvg: number,
777
+ walletBalCC: number,
778
+ slippage: number,
779
+ currentPosition: number,
780
+ currentCashCC: number,
781
+ currentLockedInValue: number,
782
+ S2: number,
783
+ Sm: number,
784
+ S3: number,
785
+ totLong: number,
786
+ totShort: number,
787
+ maxShort: number,
788
+ maxLong: number
789
+ ): number {
790
+ if (dir < 0) {
791
+ dir = -1;
792
+ } else {
793
+ dir = 1;
794
+ }
795
+ const lot = 10;
796
+ const deltaS = 1; //for derivative
797
+ const f0 = pmExcessCashAtLvg(
798
+ dir * deltaS,
799
+ lvg,
800
+ walletBalCC,
801
+ currentCashCC,
802
+ currentPosition,
803
+ currentLockedInValue,
804
+ slippage,
805
+ S2,
806
+ Sm,
807
+ S3,
808
+ totLong,
809
+ totShort
810
+ );
811
+ if (f0 < lot) {
812
+ // no trade possible
813
+ return 0;
814
+ }
815
+ // numerically find maximal trade size
816
+ let sNew = dir * lot * 10;
817
+ let s = 2 * sNew;
818
+ while (true) {
819
+ let count = 0;
820
+ while (Math.abs(sNew - s) > 1 && count < 100) {
821
+ s = sNew;
822
+ const f =
823
+ pmExcessCashAtLvg(
824
+ s,
825
+ lvg,
826
+ walletBalCC,
827
+ currentCashCC,
828
+ currentPosition,
829
+ currentLockedInValue,
830
+ slippage,
831
+ S2,
832
+ Sm,
833
+ S3,
834
+ totLong,
835
+ totShort
836
+ ) ** 2;
837
+ const f2 =
838
+ pmExcessCashAtLvg(
839
+ s + deltaS,
840
+ lvg,
841
+ walletBalCC,
842
+ currentCashCC,
843
+ currentPosition,
844
+ currentLockedInValue,
845
+ slippage,
846
+ S2,
847
+ Sm,
848
+ S3,
849
+ totLong,
850
+ totShort
851
+ ) ** 2;
852
+ let ds = (f2 - f) / deltaS;
853
+ if (ds == 0) {
854
+ sNew = s + Math.random() * ds - ds / 2;
855
+ } else {
856
+ sNew = s - f / ds;
857
+ }
858
+ count += 1;
859
+ }
860
+ if (count < 100) {
861
+ break;
862
+ }
863
+ // Newton algorithm failed,
864
+ // choose new starting value
865
+ if (dir > 0) {
866
+ sNew = Math.random() * (maxLong - currentPosition);
867
+ } else {
868
+ sNew = -Math.random() * (Math.abs(maxShort) + currentPosition);
869
+ }
870
+ }
871
+ // ensure trade maximal trade sNew does not exceed
872
+ // the contract limits
873
+ if (currentPosition + sNew < maxShort) {
874
+ sNew = maxShort - currentPosition;
875
+ } else if (currentPosition + sNew > maxLong) {
876
+ sNew = maxLong - currentPosition;
877
+ }
878
+ // round trade size down to lot
879
+ sNew = Math.sign(sNew) * Math.floor(Math.abs(sNew) / lot) * lot;
880
+ return sNew;
881
+ }
882
+
652
883
  /**
653
884
  * Find maximal trade size (short dir=-1 or long dir=1) for prediction
654
- * markets.
885
+ * markets at maximal leverage and incorporating the current position.
886
+ * Agnostic about wallet balance.
655
887
  * @param dir
656
888
  * @param currentPosition
657
889
  * @param currentCashCC
package/src/marketData.ts CHANGED
@@ -2505,4 +2505,34 @@ export default class MarketData extends PerpetualDataHandler {
2505
2505
  public async fetchPricesForPerpetual(symbol: string): Promise<IdxPriceInfo> {
2506
2506
  return this.priceFeedGetter.fetchPricesForPerpetual(symbol);
2507
2507
  }
2508
+
2509
+ /**
2510
+ * fetch prediction markets question
2511
+ * @param symbol symbol of the form "TRUMP24-USD"
2512
+ * @returns question for given symbol
2513
+ */
2514
+ public async fetchPrdMktQuestion(symbol: string): Promise<string> {
2515
+ const c = this.priceFeedGetter.getConfig().ids;
2516
+ let j = -1;
2517
+ for (let k = 0; k < c.length; k++) {
2518
+ if (c[k].symbol == symbol) {
2519
+ j = k;
2520
+ break;
2521
+ }
2522
+ }
2523
+ if (j == -1) {
2524
+ throw Error("${symbol} not found");
2525
+ }
2526
+ let origin = c[j].origin;
2527
+ const query = "https://clob.polymarket.com/markets/" + origin;
2528
+ let response = await fetch(query);
2529
+ if (response.status !== 200) {
2530
+ throw new Error(`unexpected status code: ${response.status}`);
2531
+ }
2532
+ if (!response.ok) {
2533
+ throw new Error(`failed to fetch posts (${response.status}): ${response.statusText} ${query}`);
2534
+ }
2535
+ const data = await response.json();
2536
+ return data.question;
2537
+ }
2508
2538
  }
package/src/priceFeeds.ts CHANGED
@@ -73,6 +73,9 @@ export default class PriceFeeds {
73
73
  this.triangulations = new Map<string, [string[], boolean[]]>();
74
74
  }
75
75
 
76
+ public getConfig(): PriceFeedConfig {
77
+ return this.config;
78
+ }
76
79
  // overridePriceEndpointsOfSameType overrides endpoints of config with same
77
80
  // type endpoints provided by user and returns the updated price feed
78
81
  // endpoints list.
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const D8X_SDK_VERSION = "2.1.2-alpha2";
1
+ export const D8X_SDK_VERSION = "2.1.4-alpha2";