Trading¶
The economic backbone. Players move commodities between stations whose buy/sell patterns and prices respond to local supply.
Stations (ports)¶
Codebase calls them stations (models/station.py); user-facing docs call them ports. Same thing. Each station has a class (0–11) that fixes its trading pattern.
Station classes¶
Source: services/trading_service.py, models/station.py:get_trading_pattern, Resources.aispec.
| Class | Buys | Sells |
|---|---|---|
| 0 (Sol) | special goods + colonists | special goods + colonists |
| 1 | ore | organics, equipment |
| 2 | organics | ore, equipment |
| 3 | equipment | ore, organics |
| 4 (Distribution) | — | ore, organics, equipment, fuel |
| 5 (Collection) | ore, organics, equipment, fuel | — |
| 6 | ore, organics | equipment, fuel |
| 7 | equipment, fuel | ore, organics |
| 8 (Black Hole) | ore, organics, equipment, fuel | — (premium prices) |
| 9 (Nova) | — | ore, organics, equipment, fuel (premium) |
| 10 | gourmet_food | luxury_goods, exotic_technology |
| 11 | exotic_technology | advanced components |
Sector 1 of every region holds a Class-0 station that also sells colonists (population) — see planets/colonization.md. Colonist price clamp is 30–80 cr/unit (COMMODITY_PRICE_RANGES).
Class 8 / Class 9 premium pricing¶
Class 8 (Black Hole) buys all commodities at +20% over the standard formula. Class 9 (Nova) sells all commodities at +25% over the standard formula. These multipliers are applied after the base supply/demand calculation but before reputation/rank modifiers.
Status: 🚧 Partial —
is_premium_buyer/is_premium_sellerflags exist onStation(models/station.py), but the multiplier logic is not applied inservices/trading_service.py:apply_modifiers. The numbers above are the design target.
Class 11 commodity drift¶
🐛 Bug — Class 11 commodity drift. Current docs describe Class 11 as buying
exotic_technologyand sellingadvanced_components, butadvanced_componentsis not inCOMMODITY_PRICE_RANGES(services/trading_service.py) and is not traded at any other port. Two resolutions: - Option A (preferred): rename Class 11's "advanced_components" toexotic_technology(single-commodity premium specialist). - Option B: addadvanced_componentsto the commodity catalog (COMMODITY_PRICE_RANGES) with a price range and document the gameplay loop that produces it.The design target is Option A pending team confirmation.
Destruction & recovery¶
A destroyed station enters a 24-hour automated rebuild cycle. During recovery:
- The station is non-functional (no docking, no trading, no services).
- Defenses are inactive.
- Cargo, drones, and credits in storage are preserved.
After 24 hours the station auto-rebuilds at reduced capacity (50% of pre-destruction commodity inventory; defenses must be re-purchased).
Status: 📐 Design-only — auto-recovery logic does not exist in code.
Bang generator commodity gap¶
🐛 Bug — Procedural-port commodity coverage. The world generator
sw2102-bangemits stations with only three of the seven core commodities:fuel_ore(mapped toore),organics, andequipment. The other four core commodities (gourmet_food,fuel,exotic_technology,luxury_goods) are referenced throughout the spec but do not appear at any procedurally-generated station.The design target is for all 7 core commodities to be tradable at procedural ports through the binary class-encoding system. Two resolution paths:
- Extend Bang's commodity enum and port-class generator to emit all 7 commodities.
- Or post-process Bang output via a translator (see
../../OPERATIONS/bang-integration.md) to inject the missing commodities at gameserver bootstrap.Until resolved, gourmet_food / fuel / exotic_technology / luxury_goods are only available via crafting, special locations (Stardock at Sector 1, TradeDocks), or rare events. This is not the intended Launch state.
Pricing model¶
services/trading_service.py:calculate_dynamic_price runs a supply/demand formula plus a fixed spread:
supply_ratio = current_quantity / capacity ∈ [0,1]
midpoint = base_price × (1.5 - supply_ratio)
sell_price = midpoint × 1.15 # station charges player
buy_price = midpoint × 0.85 # station pays player
Result is clamped to commodity-specific ranges:
| Commodity | min | max |
|---|---|---|
| ore | 15 | 45 |
| organics | 8 | 25 |
| gourmet_food | 30 | 70 |
| fuel | 20 | 60 |
| equipment | 50 | 120 |
| exotic_technology | 150 | 300 |
| luxury_goods | 75 | 200 |
| colonists | 30 | 80 |
The 15% spread guarantees sell_price > buy_price (with a final buy_price = sell_price - 1 fallback if rounding ever inverts). This is the structural source of all arbitrage.
Stock regen¶
tick_production runs periodically — each commodity advances quantity = min(capacity, quantity + production_rate). Production rates are per-station JSONB on Station.commodities.
Market history¶
Per-(station, commodity) MarketPrice rows track:
- buy_price, sell_price
- previous_buy_price, previous_sell_price
- price_trend — relative change since last tick
- supply_level, demand_level — for analytics
- volatility — derived from price_variance
Drives realtime feeds in services/realtime_market_service.py and ARIA market intelligence.
Trade transaction flow¶
- Player navigates ship to station's sector.
- Dock (1 turn). Sets
Player.is_docked = True,current_port_id. - Trade as many commodities as desired — each transaction is 0 turns.
- Buy: credits debited, cargo credited, station stock decremented.
- Sell: cargo debited, credits credited, station stock incremented.
- Undock (1 turn). Free to move.
TradingService.can_player_trade enforces docking + same-sector before any transaction.
API: services/gameserver/src/api/routes/trading.py.
Faction price modifiers¶
Player's faction reputation modifies the station's effective price (see factions-and-teams.md):
| Reputation tier | Trade multiplier |
|---|---|
| ≥ +700 (EXALTED) | ×0.85 |
| ≥ +500 | ×0.90 |
| ≥ +300 | ×0.95 |
| ≥ +100 | ×0.97 |
| Neutral | ×1.00 |
| ≤ −299 | ×1.05 |
| ≤ −499 | ×1.15 |
| ≤ −699 | ×1.30 |
| ≤ −700 | ×1.50 |
Personal reputation also adjusts pricing: ≤ −500 = +20% markup, ≥ +500 = −10% discount (personal_reputation_service.get_reputation_info).
Military rank stacks on top with the rank-defined trading bonus (0% to +50% from Recruit to Fleet Admiral).
Haggling¶
Two negotiation paths exist: numerical haggling (back-and-forth offers, max 4 rounds) and narrative haggling (AI-evaluated persuasive statements with anti-exploitation safeguards). See haggling.md for the full design, evaluation rubric, and anti-gaming controls.
Black market¶
Off-the-books trades available at certain stations and via specific NPCs — illicit commodities, stolen goods, and reputation-gated routes. See black-market.md.
Trade contracts¶
Cargo-delivery contracts, escort contracts, and standing orders that pay out on completion. See contracts.md.
TradeDock & shipyard¶
TradeDocks are rare premium stations combining a high-end trading hub with a 12-slip player shipyard (rentable per-day construction of all ship classes including the Warp Jumper). See tradedock-shipyard.md.
Port ownership¶
Players meeting trade-volume, faction-standing, and mission thresholds can buy a port and earn tariff income, supply priority, and configure pricing/defenses. See port-ownership.md.
Player-facing affordances¶
- Trading UI: two-column "Port Selling" vs "Your Cargo" with current prices, trend arrows, and quantity controls.
- Profit/loss preview before confirming.
- Per-trade confirmation modal.
- Market price history charts (via realtime market WebSocket).
- ARIA recommendations overlay (which commodities, which ports).
- Cargo hold visualization with drag-and-drop arrangement.
Source map¶
| Topic | Path |
|---|---|
| Trading service (pricing, ticks) | services/gameserver/src/services/trading_service.py |
| Realtime market | services/gameserver/src/services/realtime_market_service.py |
| Market prediction | services/gameserver/src/services/market_prediction_engine.py |
| Station model + class patterns | services/gameserver/src/models/station.py |
| Market price/transaction models | services/gameserver/src/models/market_transaction.py (canonical), resource.py (catalog metadata) |
| Trade API | services/gameserver/src/api/routes/trading.py |
| Admin economy tools | services/gameserver/src/api/routes/admin_economy.py, admin_comprehensive.py |
| Economy analytics | services/gameserver/src/services/economy_analytics_service.py |
| Faction trade modifier | services/gameserver/src/services/faction_service.py |
| Personal-rep modifier | services/gameserver/src/services/personal_reputation_service.py |
Status: 🚧 Partial — the canonical transaction table (
enhanced_market_transactions, defined inmarket_transaction.py) is the target schema. A legacy resource-enum-keyedmarket_transactionstable (defined inresource.py) still exists in the schema and will be removed once all reads/writes migrate off it.