Configuration
DynaTrade is configured through two main files plus optional language files.
| File | Purpose |
|---|---|
plugins/DynaTrade/config.yml |
Global market behavior, template selection, spreads, sounds, apply controls, and operational logs |
plugins/DynaTrade/items.yml |
The tradable item catalog and per-item tuning |
plugins/DynaTrade/items_pt.yml |
Optional Portuguese item-name overrides for server-side item presentation |
plugins/DynaTrade/languages/messages_en.yml |
English player-facing and GUI text |
plugins/DynaTrade/languages/messages_pt.yml |
Portuguese player-facing and GUI text |
After editing any of these files, run /dt reload.
If /dt status later reports degraded mode after a failed reload, restart the
server before resuming trading. That means the old runtime was already stopped
and the replacement runtime could not be created.
Do not manually edit market-state.yml, pending-signals.yml, pending-signals.log, cycle-checkpoint.yml, trade-runtime-state.yml, or pending-deliveries.yml. Those files contain live runtime state managed by DynaTrade.
config.yml
Language
language: en
Bundled values:
enpt
Economy template
economy:
template: BALANCED
Templates define the default market personality.
| Template | Behavior |
|---|---|
STABLE |
Slow and predictable price movement |
BALANCED |
Recommended default for most servers |
VOLATILE |
More visible reactions to player pressure |
HARDCORE |
Aggressive price movement and sharper swings |
If you are unsure, start with BALANCED.
Economy overrides
Use overrides when you want to customize the selected template instead of replacing it entirely.
economy:
overrides:
market: {}
categories: {}
category-behavior: {}
pricing: {}
Useful category-level tuning:
economy:
overrides:
category-behavior:
AGRICULTURE:
sigma: 0.22
vref: 240
inactive-gamma: 0.28
idle-cycle-threshold: 4
Supported categories:
MININGAGRICULTUREMISCELLANEOUSBUILDINGMAGICALCHEMY
Buy and sell spread
pricing:
buy-spread: 0.06
sell-spread: 0.10
Example at market price 100:
- buy price =
106 - sell price =
90
Higher spread increases friction. Lower spread makes trading closer to the market reference price.
Idle recovery
pricing:
idle-cycle-threshold: 7
idle-deviation-percent-threshold: 0.15
idle-deviation-absolute-threshold: 0.20
inactive-gamma: 0.20
Idle recovery helps stale items move back toward their baseline when they have been quiet for several cycles.
Player-aware pressure normalization
pricing:
player-aware-pressure:
target-participation-players: 4
min-participation-factor: 0.25
active-participation-reach:
enabled: true
min-active-reach-factor: 0.50
active-participant-floor: 4
active-participant-cap: 30
reach-weight: 0.25
Player-aware pressure normalization is part of DynaTrade's base pricing model. It does not need to be enabled.
The top-level values tune the base participation normalization:
| Key | Meaning |
|---|---|
target-participation-players |
Unique players on the dominant pressure side needed for full pressure in one cycle |
min-participation-factor |
Minimum pressure factor when participation data exists but is below the target |
Default behavior:
| Unique players | Pressure factor |
|---|---|
| 1 | 0.25 |
| 2 | 0.50 |
| 3 | 0.75 |
| 4+ | 1.00 |
When participation data is not available, DynaTrade uses the original raw pressure unchanged. This covers recovery replay, older aggregate signals, and internal signals without player identity.
The nested active-participation-reach block tunes the additional reach refinement:
| Key | Meaning |
|---|---|
enabled |
Enables or disables only the active-reach refinement layer |
min-active-reach-factor |
Lower bound for the active-reach factor |
active-participant-floor |
Minimum active-economy participant count considered by the reach layer |
active-participant-cap |
Maximum active-economy participant count considered by the reach layer |
reach-weight |
How strongly active reach influences the final factor |
Important behavior:
enabled: falsedisables only the active-reach refinement layer- base player-aware normalization remains part of pricing behavior
- the reach layer only refines cycles that already reached full participation confidence
- invalid or unavailable active-participant data falls back automatically to the base participation result
With the current defaults, 4/4 active participants stays at full confidence while 4/30 is softened to a final factor of 0.875.
Effective VREF calibration
The current line includes effective VREF (volume reference) calibration with state persistence and diagnostics.
pricing:
calibration:
enabled: true
smoothing-alpha: 0.25
max-effective-vref-multiplier: 8
min-samples: 5
history-size: 8
blend-weight: 0.65
max-change-per-update: 0.25
How calibration works:
DynaTrade tracks observed volume per item over multiple pricing cycles. When enough samples exist, it computes a smoothed effective VREF that replaces the static configured vref in the pressure calculation. This helps common high-volume items avoid overreacting to normal activity while preserving configured VREF as the anchor.
Key parameters:
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch. When false, configured vref is always used. |
smoothing-alpha |
0.25 |
EMA smoothing factor for observed VREF. Lower values smooth more. Range: 0.0–1.0. |
max-effective-vref-multiplier |
8 |
Upper bound for effective VREF relative to configured VREF. Minimum: 1.0. |
min-samples |
5 |
Minimum cycles of observed data before effective VREF moves away from configured VREF. |
history-size |
8 |
Runtime ring-buffer size for observed volume history. Always at least min-samples. |
blend-weight |
0.65 |
Blend between configured VREF and smoothed observed VREF once calibrated. Range: 0.0–1.0. |
max-change-per-update |
0.25 |
Maximum calibrated VREF movement per cycle after warm-up. Range: 0.0–1.0. |
Important behavior:
- calibration updates only during pricing cycles with trade activity
- calibrated state (smoothed observed VREF, sample count, last-updated cycle) is persisted in
market-state.ymland restored on startup or/dt reload - if calibration state is missing, disabled, or invalid, the configured
vrefis used as a safe fallback /dt itemshows a-- Calibration --section with state, reason, VREF ratio, sample count, history size, and cap/floor flags
What it also does today:
- computes item-level
riskScore - classifies
VolatilityProfile - dampens caution for thin-market conditions inside the risk path
- exposes adaptive-spread diagnostics, including per-item/global max bonus caps
- applies live adaptive spread in the real buy/sell quote path when calibration is enabled and the item is calibrated
Operational logs
pricing:
batch-tick-log-enabled: false
batch-empty-log-enabled: false
batch-drain-summary-log-enabled: true
batch-pricing-summary-log-enabled: true
Recommended production posture:
- keep tick and empty logs off
- keep summary logs on
- enable extra logs only when diagnosing behavior
Apply backpressure
The 0.8.6 line includes bounded main-thread apply draining for durable trades.
apply:
max-per-tick: 8
drain-deadline-ms: 15
What these do:
| Key | Meaning |
|---|---|
max-per-tick |
Maximum durable trades applied on the Bukkit thread in one tick |
drain-deadline-ms |
Maximum time budget for one apply drain pass |
Validated production defaults:
max-per-tick: 8drain-deadline-ms: 15
Change these only if you are actively benchmarking your own environment.
Trade history retention
history:
inactive-player-ttl-days: 7
What this does:
| Key | Meaning |
|---|---|
inactive-player-ttl-days |
Removes cached trade-history state for players who have not been read or indexed for that many days |
Notes:
- use
0to disable this TTL-based eviction - this does not change live prices or pending trade state
- it keeps per-player history retention bounded over time
Trade admission control
The current runtime also includes overload protection for accepted-but-not-yet-applied trades.
trade:
admission:
enabled: true
max-pending-applies-global: 5000
max-pending-applies-per-player: 50
reject-when-full: true
backlog-guard:
enabled: true
reject-when-backlog-above: 4500
accept-when-backlog-below: 2500
What these do:
| Key | Meaning |
|---|---|
enabled |
Turns admission control on or off |
max-pending-applies-global |
Hard cap for pending applies across the whole server |
max-pending-applies-per-player |
Per-player cap for pending applies |
reject-when-full |
Rejects new trades instead of allowing unbounded queue growth |
backlog-guard.* |
Hysteresis guard that rejects while backlog is high and reopens when it falls |
Recommended posture:
- keep these defaults unless you are running your own load validation
- treat this as server protection, not economy tuning
Momentum signal
The current runtime can compute a recent-cycle momentum signal per item.
momentum:
enabled: true
window_size: 3
smoothing_alpha: 0.7
sensitivity: 0.20
max_change_per_cycle: 0.30
Important:
- this signal does not change the core market price directly
- it exists to summarize recent cycle direction in a bounded way
- it is consumed by the optional quote-adjustment layer when that layer is enabled
Optional quote-adjustment layer
The current config still uses the internal compatibility key premium, but this is best understood as an optional quote-adjustment layer.
premium:
momentum-spread:
enabled: false
tau-base: 0.05
tau-min: 0.01
tau-max: 0.20
k-sell: 0.10
k-buy: 0.10
What this means:
- disabled by default
- can widen or tighten buy and sell spreads using the momentum signal
- does not alter the core economic market price
If you do not need this behavior yet, leave it disabled.
Observability toggles
The current runtime also includes optional admin-facing visibility toggles.
observability:
admin-internal-status-enabled: false
admin-benchmark-status-enabled: false
What these do:
| Key | Meaning |
|---|---|
admin-internal-status-enabled |
Adds queue, backlog, and backpressure details to /dt status |
admin-benchmark-status-enabled |
Adds benchmark-oriented internal timing output to /dt status |
Recommended posture:
- leave both off in normal operation
- enable them only during diagnostics or controlled validation
Automatic file migration
On startup and reload, DynaTrade can merge missing bundled keys into:
config.ymlitems.ymlitems_pt.ymllanguages/messages_en.ymllanguages/messages_pt.yml
Important behavior:
- existing custom values are preserved
- only missing keys are added automatically
- upgraded files receive a timestamped backup before the merged file is saved
- if a message key is missing from disk, DynaTrade can still fall back to the bundled message inside the jar
Sounds
sounds:
enabled: true
volume: 0.6
ui-cooldown-ms: 120
cycle-update-enabled: true
pitch:
buy-base: 1.2
sell-base: 1.0
To disable sounds entirely:
sounds:
enabled: false
items.yml
Every tradable item is defined under items:. Vanilla items use an uppercase Bukkit Material key. The current technical-preview line also supports configured custom items backed by a Bukkit material and matching metadata; see Configured Custom Items.
Minimum example:
items:
DIAMOND:
display-name: "Diamond"
base-price: 150.0
category: MINING
Important fields:
| Field | Meaning |
|---|---|
key such as DIAMOND |
Market key; vanilla entries use a Minecraft material name in uppercase |
display-name |
Player-facing name |
description |
Optional lore text shown in the GUI |
base-price |
Long-term baseline price |
category |
Market group |
sigma |
Price sensitivity override |
vref |
Reference volume override |
inactive-gamma |
Idle recovery override |
idle-cycle-threshold |
Per-item stale threshold |
min-price-factor |
Floor multiplier relative to base price |
max-price-factor |
Ceiling multiplier relative to base price |
display-name is still supported and remains a valid editorial fallback. When the server language is Portuguese, DynaTrade now resolves item names in this order:
plugins/DynaTrade/items_pt.yml- bundled
items_pt.ymlinside the jar display-namefromitems.yml- automatic formatting from the item key, such as
NETHERITE_INGOT -> Netherite Ingot
This means you can keep items.yml focused on market tuning while using items_pt.yml only for Portuguese naming overrides.
items_pt.yml
This file is optional and is only used for Portuguese item-name presentation.
Minimum example:
version: 1
items:
DIAMOND:
display-name: "Diamante"
IRON_INGOT:
display-name: "Barra de Ferro"
Use this file when:
- you want Portuguese names without changing your main catalog
- you want to override the bundled default Portuguese translations
- you want admin-controlled naming for the GUI,
/price, and trade receipts
Do not use this file to change item keys. Internal item identity remains the material key from items.yml.
Recommended starting point
For most servers:
language: en
economy:
template: BALANCED
pricing:
buy-spread: 0.06
sell-spread: 0.10
player-aware-pressure:
target-participation-players: 4
min-participation-factor: 0.25
active-participation-reach:
enabled: true
min-active-reach-factor: 0.50
active-participant-floor: 4
active-participant-cap: 30
reach-weight: 0.25
apply:
max-per-tick: 8
drain-deadline-ms: 15
Then tune categories and specific items only after observing real player behavior.
Quick tuning guide
| Goal | What to adjust |
|---|---|
| Market feels too slow | Lower vref, raise sigma, or shorten cycle interval |
| Market feels too chaotic | Raise vref, lower sigma, or tighten price-factor caps |
| Rare items move too little | Raise per-item sigma and lower per-item vref |
| Common items crash too fast | Lower sigma and raise vref |
| Recovery feels too slow | Raise inactive-gamma or lower idle-cycle-threshold |
| Burst load feels rough on your server | Benchmark before changing apply.* defaults |