Skip to main content

Dynamic Pricing

Dynamic Pricing

Dynamic pricing allows shop item prices to fluctuate automatically based on how many times items have been bought and sold across the entire server. As players buy more of an item, the price rises; as players sell more, the price falls.

Prices are driven by configurable math formulas and are clamped between a minimum and maximum percentage of the item's base price.

Category-Level Configuration

Dynamic pricing is configured per category in the category config file. It applies to every item in that category unless overridden per item.

dynamic-pricing:
enabled: false # Whether dynamic pricing is active for this category.
max-increase: 1.5 # The maximum price as a multiplier of base price (1.5 = 150%).
max-decrease: 0.5 # The minimum price as a multiplier of base price (0.5 = 50%).

decay:
enabled: false # Whether price decay is active for this category.
rate: 0.1 # Percentage of counters removed per period (0.1 = 10%).
period: 1440 # Period in minutes (1440 = 24 hours).

buy:
enabled: true
formula: "%base_price% * (1 + 0.0781 * log(1 + max(%buys% - %sells%, 0)) - 0.0781 * log(1 + max(%sells% - %buys%, 0)))"

alt-buy:
enabled: true
formula: "%base_price% * (1 + 0.0781 * log(1 + max(%buys% - %sells%, 0)) - 0.0781 * log(1 + max(%sells% - %buys%, 0)))"

sell:
enabled: true
formula: "%base_price% * (1 + 0.0781 * log(1 + max(%buys% - %sells%, 0)) - 0.0781 * log(1 + max(%sells% - %buys%, 0)))"

enabled

Whether dynamic pricing is active for this category. When false, all item prices remain at their configured base values.

max-increase

The maximum price multiplier. A value of 1.5 means prices can rise to at most 150% of the item's base price.

max-decrease

The minimum price multiplier. A value of 0.5 means prices can fall to at most 50% of the item's base price.

Per-price-type options

Each price type (buy, alt-buy, sell) supports:

KeyDescription
enabledWhether dynamic pricing is active for this price type. Defaults to the category enabled value.
max-increaseOverride max-increase for this price type only.
max-decreaseOverride max-decrease for this price type only.
formulaThe math formula used to calculate the price.
dynamic-pricing:
enabled: true
max-increase: 1.5
max-decrease: 0.5
buy:
max-increase: 2.0 # Buy price can go higher than sell
formula: "%base_price% * (1 + 0.0781 * log(1 + max(%buys% - %sells%, 0)) - 0.0781 * log(1 + max(%sells% - %buys%, 0)))"
sell:
enabled: false # Disable dynamic pricing for sell price in this category

Formula Placeholders

The following placeholders are available for use in formulas:

PlaceholderDescription
%base_price%The item's configured base price value
%buys%Total number of times this item has been bought across the whole server
%sells%Total number of times this item has been sold across the whole server

Read here for more info on supported operators and functions: Math.

Default Formula

The default formula responds to net demand — the difference between buys and sells. Only the net position matters, so buying and selling cancel each other out exactly:

  • 600 net buys (e.g. 600 bought, 0 sold) → price reaches max-increase
  • 600 net sells (e.g. 0 bought, 600 sold) → price reaches max-decrease
  • Equal buys and sells → price stays at base, regardless of volume
%base_price% * (1 + 0.0781 * log(1 + max(%buys% - %sells%, 0)) - 0.0781 * log(1 + max(%sells% - %buys%, 0)))

To change how many net transactions it takes to reach the cap, adjust the 0.0781 coefficient:

coefficient = (max-increase - 1) / ln(1 + target_transactions)

For example, to reach the cap at 1000 net buys with max-increase: 1.5:

coefficient = 0.5 / ln(1001) ≈ 0.0724

Decay

By default, dynamic pricing counters persist indefinitely — prices stay elevated or depressed until enough opposite transactions occur. Decay gradually reduces both counters over time, drifting prices back toward their base values even when transaction activity slows down.

dynamic-pricing:
enabled: true
decay:
enabled: true # Whether decay is active for this category.
rate: 0.1 # 10% of counters removed per period.
period: 1440 # Period in minutes (default: 1440 = 24 hours).

decay.enabled

Whether decay is active for this category. Defaults to false.

decay.rate

The percentage of the buy and sell counters removed each period. A value of 0.1 reduces both counters by 10% every period.

decay.period

How often decay is applied, in minutes. Defaults to 1440 (24 hours).

How decay works

Both the buy and sell counters are multiplied by (1 - rate) each period. Since the formula uses net demand (buys - sells), reducing both counters proportionally also reduces the net demand — pulling prices back toward base. Equal buying and selling still cancels out, but prolonged inactivity will always eventually return prices to base.

Decay is category-level only and is inherited by all items in the category, including those with per-item pricing overrides.

To manually reset dynamic pricing counters for an item, use /ecoshop resetdynamicpricing <id/all>.

Per-Item Overrides

Individual items can override the category dynamic pricing settings. Per-item overrides are placed inside the buy, alt-buy, or sell sections of the item config alongside value and type.

Any field not specified inherits from the category dynamic-pricing block. Decay is category-level only and cannot be overridden per item — it is always inherited from the category.

- id: diamond
item: diamond
gui:
column: 5
row: 3
page: 1
buy:
value: 100
type: coins
display: "$%value%"
dynamic-pricing: # Override buy dynamic pricing for this item only
enabled: true
max-increase: 3.0 # This item's buy price can go up to 300% of base
max-decrease: 0.5
formula: "%base_price% * (1 + 0.0781 * log(1 + max(%buys% - %sells%, 0)) - 0.0781 * log(1 + max(%sells% - %buys%, 0)))"
sell:
value: 50
type: coins
display: "$%value%"
dynamic-pricing: # Override sell dynamic pricing for this item only
enabled: false # Disable sell dynamic pricing for this item

Read here for more info on configuring items: How to make an Item.