Skip to content

SkyBlock Economy (computed)

Derived SkyBlock economy statistics computed from the parsed bazaar, auction house, fire sale, and museum shapes. Sources: src/computed/skyblock/bazaar-product.ts, auction.ts, firesale.ts, museum.ts, and ended-auctions.ts.

Conventions used on this page (from the shared ratio helpers):

  • Ratios and averages are bare numbers rounded to 2 decimals. A zero denominator yields the numerator (so ratio(x, 0) is x).
  • *Percent and *SharePercent fields are percentages on a 0 to 100 scale, rounded to 2 decimals (0 when the whole is 0).
  • Time-based fields are milliseconds unless named otherwise; fields comparing against the current time are evaluated with Date.now() at call time.

Bazaar

BazaarProductComputed

Produced by computeBazaarProduct(raw: BazaarProduct): BazaarProductComputed. The raw quickStatus prices are weighted averages over the whole order book, so the true top-of-book insta-buy and insta-sell prices are taken from the first entries of buySummary and sellSummary instead.

ts
export interface BazaarProductComputed {
  readonly instantBuyPrice: number;
  readonly instantSellPrice: number;
  readonly spread: number;
  readonly marginPercent: number;
  readonly averageBuyOrderSize: number;
  readonly averageSellOrderSize: number;
  readonly weeklyTradedVolume: number;
  readonly weeklyDemandSupplyRatio: number;
  readonly averageDailyBuyVolume: number;
  readonly averageDailySellVolume: number;
}
FieldFormula / meaning
instantBuyPricePrice you pay to insta-buy one unit right now: raw.buySummary[0].pricePerUnit, or 0 when the buy side of the book is empty.
instantSellPricePrice you receive to insta-sell one unit right now: raw.sellSummary[0].pricePerUnit, or 0 when the sell side is empty.
spreadInsta-buy minus insta-sell: instantBuyPrice - instantSellPrice (the gross flip profit per unit before taxes).
marginPercentSpread as a percentage (0 to 100) of the insta-sell price: percent(spread, instantSellPrice).
averageBuyOrderSizeAverage units per open buy order: quickStatus.buyVolume / quickStatus.buyOrders.
averageSellOrderSizeAverage units per open sell order: quickStatus.sellVolume / quickStatus.sellOrders.
weeklyTradedVolumeTotal units moved in the trailing week on both sides: buyMovingWeek + sellMovingWeek.
weeklyDemandSupplyRatioWeekly buy volume per unit of weekly sell volume, as a bare ratio: buyMovingWeek / sellMovingWeek (above 1 means demand outpaces supply).
averageDailyBuyVolumebuyMovingWeek / 7.
averageDailySellVolumesellMovingWeek / 7.

Auctions

AuctionComputed

Produced by computeAuction(raw: SkyBlockAuction): AuctionComputed for a single active auction. A null startedAt or endsAt is treated as epoch 0 for the time math. For BIN listings the bid amount is ignored entirely (topBid is forced to 0), so currentPrice is the BIN price stored in startingBid.

ts
export interface AuctionComputed {
  readonly ended: boolean;
  readonly timeLeftMs: number;
  readonly durationMs: number;
  readonly elapsedPercent: number;
  readonly bidCount: number;
  readonly uniqueBidderCount: number;
  readonly currentPrice: number;
  readonly highestBidderUuid: string | null;
  readonly bidPremiumPercent: number;
}
FieldFormula / meaning
endedWhether the end time has passed: timeLeftMs === 0.
timeLeftMsMilliseconds until endsAt, floored at 0: max(endsAt - now, 0).
durationMsScheduled auction length: max(endsAt - startedAt, 0).
elapsedPercentPercentage (0 to 100) of the duration already elapsed: percent(clamp(now - startedAt, 0, durationMs), durationMs).
bidCountraw.bids.length.
uniqueBidderCountNumber of distinct bidder UUIDs across raw.bids.
currentPriceEffective price with a fallback chain: highestBidAmount when the auction is not BIN and that amount is greater than 0; otherwise startingBid (which for BIN listings is the buy-it-now price).
highestBidderUuidUUID of the bidder with the largest single bid amount (arg-max over raw.bids with a floor of 0); null when there are no bids with a positive amount.
bidPremiumPercentHow far bidding has driven the price above the start, as a percentage (0 to 100 scale, unbounded above): percent(topBid - startingBid, startingBid) when topBid > 0, else 0. Always 0 for BIN listings.

EndedAuctionsComputed

Produced by computeEndedAuctions(raw: readonly SkyBlockAuction[]): EndedAuctionsComputed over a batch of recently ended (sold) auctions.

ts
export interface EndedAuctionsComputed {
  readonly saleCount: number;
  readonly binCount: number;
  readonly bidSaleCount: number;
  readonly binSharePercent: number;
  readonly totalSaleValue: number;
  readonly averageSalePrice: number;
  readonly medianSalePrice: number;
  readonly minSalePrice: number;
  readonly maxSalePrice: number;
  readonly uniqueBuyerCount: number;
  readonly uniqueSellerCount: number;
  readonly firstSoldAt: Date | null;
  readonly lastSoldAt: Date | null;
  readonly salesPerMinute: number;
}
FieldFormula / meaning
saleCountraw.length: number of sales in the batch.
binCountNumber of sales where auction.bin is true.
bidSaleCountRegular (bid) sales: saleCount - binCount.
binSharePercentPercentage (0 to 100) of sales that were BIN: percent(binCount, saleCount).
totalSaleValueSum of auction.price across all sales.
averageSalePricetotalSaleValue / saleCount as a bare ratio (equals totalSaleValue when the batch is empty).
medianSalePriceMedian of the sale prices (mean of the middle two for an even count; 0 for an empty batch).
minSalePriceLowest sale price, or 0 for an empty batch.
maxSalePriceHighest sale price, or 0 for an empty batch.
uniqueBuyerCountNumber of distinct buyer values.
uniqueSellerCountNumber of distinct auctioneer values.
firstSoldAtEarliest non-null soldAt timestamp as a Date, or null when no sale has one.
lastSoldAtLatest non-null soldAt timestamp as a Date, or null.
salesPerMinuteSales throughput over the observed window: saleCount / spanMinutes, where spanMinutes = (lastSoldAt - firstSoldAt) / 60000 (0 when timestamps are missing; a zero span yields saleCount per the ratio convention).

Fire sales

FireSaleComputed

Produced by computeFireSale(raw: SkyBlockFireSale): FireSaleComputed. All time fields compare raw.startTimestamp and raw.endTimestamp (epoch milliseconds) against Date.now().

ts
export interface FireSaleComputed {
  readonly hasStarted: boolean;
  readonly hasEnded: boolean;
  readonly isActive: boolean;
  readonly timeUntilStartMs: number;
  readonly timeUntilEndMs: number;
  readonly durationMs: number;
  readonly elapsedPercent: number;
  readonly totalStockValue: number;
}
FieldFormula / meaning
hasStartedstartTimestamp - now <= 0.
hasEndedendTimestamp - now <= 0.
isActivehasStarted && !hasEnded.
timeUntilStartMsMilliseconds until the sale opens: max(startTimestamp - now, 0).
timeUntilEndMsMilliseconds until the sale closes: max(endTimestamp - now, 0).
durationMsSale window length: max(endTimestamp - startTimestamp, 0).
elapsedPercentPercentage (0 to 100) of the window elapsed: percent(clamp(now - startTimestamp, 0, durationMs), durationMs).
totalStockValueGems value of the full stock: raw.amount * raw.price.

Museum

MuseumMemberComputed

Produced by computeMuseumMember(raw: SkyBlockMuseumMember): MuseumMemberComputed for one profile member's museum. Donations are the union of raw.items (regular donations) and raw.special (special items); donation timestamps ignore entries with a null donatedAt.

ts
export interface MuseumMemberComputed {
  readonly donatedItemCount: number;
  readonly specialItemCount: number;
  readonly totalDonationCount: number;
  readonly featuredItemCount: number;
  readonly borrowedItemCount: number;
  readonly firstDonatedAt: Date | null;
  readonly lastDonatedAt: Date | null;
  readonly valuePerDonation: number;
}
FieldFormula / meaning
donatedItemCountraw.items.length: regular museum donations.
specialItemCountraw.special.length: special item donations.
totalDonationCountdonatedItemCount + specialItemCount.
featuredItemCountRegular items placed in a featured slot: entries of raw.items with featuredSlot !== null.
borrowedItemCountRegular items currently borrowed back: entries of raw.items with borrowing set.
firstDonatedAtEarliest non-null donatedAt across items and specials, or null when none exists.
lastDonatedAtLatest non-null donatedAt across items and specials, or null.
valuePerDonationAverage museum value per donation, as a bare ratio: raw.value / totalDonationCount (equals raw.value when there are no donations).

MuseumComputed

Produced by computeMuseum(raw: SkyBlockMuseum): MuseumComputed over all members of a profile's museum.

ts
export interface MuseumComputed {
  readonly memberCount: number;
  readonly appraisedMemberCount: number;
  readonly totalValue: number;
  readonly totalDonatedItemCount: number;
  readonly totalSpecialItemCount: number;
  readonly totalDonationCount: number;
  readonly averageValuePerMember: number;
  readonly averageDonationsPerMember: number;
  readonly topValueMemberUuid: string | null;
  readonly topDonorMemberUuid: string | null;
  readonly lastDonatedAt: Date | null;
}
FieldFormula / meaning
memberCountNumber of member entries in raw.members.
appraisedMemberCountMembers whose appraisal flag is set.
totalValueSum of member.value across all members.
totalDonatedItemCountSum of member.items.length across all members.
totalSpecialItemCountSum of member.special.length across all members.
totalDonationCounttotalDonatedItemCount + totalSpecialItemCount.
averageValuePerMembertotalValue / memberCount as a bare ratio.
averageDonationsPerMembertotalDonationCount / memberCount as a bare ratio.
topValueMemberUuidUUID of the member with the highest value (arg-max with a floor of 0); null when no member has a positive value.
topDonorMemberUuidUUID of the member with the most donations (items.length + special.length, arg-max with a floor of 0); null when no member has any.
lastDonatedAtLatest non-null donatedAt across every member's items and specials, or null.

Released under the MIT License.