Skip to content

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_seller flags exist on Station (models/station.py), but the multiplier logic is not applied in services/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_technology and selling advanced_components, but advanced_components is not in COMMODITY_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" to exotic_technology (single-commodity premium specialist). - Option B: add advanced_components to 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-bang emits stations with only three of the seven core commodities: fuel_ore (mapped to ore), organics, and equipment. 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

  1. Player navigates ship to station's sector.
  2. Dock (1 turn). Sets Player.is_docked = True, current_port_id.
  3. Trade as many commodities as desired — each transaction is 0 turns.
  4. Buy: credits debited, cargo credited, station stock decremented.
  5. Sell: cargo debited, credits credited, station stock incremented.
  6. 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 in market_transaction.py) is the target schema. A legacy resource-enum-keyed market_transactions table (defined in resource.py) still exists in the schema and will be removed once all reads/writes migrate off it.