A Python utility for calculating production profits in Sim Companies using the Simcotools API.
- Rich UI: Uses the
richlibrary for beautiful tables, colors, progress indicators, and formatted logs. - Real-time Data: Fetches the latest resource data and market VWAPs (Volume Weighted Average Prices) from the Simcotools API.
- Profit Calculation: Calculates hourly profit by accounting for:
- Selling price (at specific quality levels).
- 4% market exchange fee (0% in direct contract mode).
- Production wages (with optional 3% reduction for robots).
- Administrative Overhead costs.
- Input material costs.
- Transportation costs (50% reduction in direct contract mode).
- Data Persistence: Automatically saves fetched API data to
resources.jsonandvwaps.jsonfor inspection. - Search & Filter: Search for specific resources or filter calculations by a target quality level.
- Direct Contract Mode: Support for calculating profits when trading directly with other players.
- Prospecting Simulation: Simulate the probability and expected time/attempts to reach a target abundance level in mines/wells using a Gaussian distribution.
- Lifecycle ROI Analysis: Calculate the optimal building level for abundance resources by simulating production from start abundance down to 85%, accounting for build time and scrapping losses (100% recovery for Lv 1-2, 50% for Lv 3+).
simtools/
├── __init__.py # Package exports
├── models/
│ ├── __init__.py
│ ├── building.py # Building class - production facilities
│ └── resource.py # Resource class - producible items
├── api.py # SimcoAPI client for fetching game data
├── calculator.py # Profit and ROI calculation logic
├── cli.py # Command-line interface and display
└── data/ # Static data files
├── buildings.json
├── abundance_resources.json
└── seasonal_resources.json
main.py # Entry point
Resource: Represents a producible item with production rate, wages, inputs, and profit calculation.Building: Represents a production facility with construction costs and the resources it produces.SimcoAPI: Client for fetching resource and price data from the Simcotools API.
This project uses uv for dependency management.
- Clone the repository.
- Install dependencies:
uv sync
Pre-built standalone executables for Windows, Linux, and macOS are available in the Releases section. Download the appropriate executable for your platform and run it directly without needing Python installed.
To build a standalone executable yourself:
-
Install development dependencies:
uv sync --all-groups
-
Build the executable:
uv run pyinstaller simtools.spec
-
The executable will be created in the
dist/directory.
Run the script using uv run or directly with python if dependencies are installed.
uv run main.py [command] [options]Check the current version:
uv run main.py --version
# or
uv run main.py -VSimtools uses a subcommand structure for better organization:
Calculate and display production profits for resources.
Options:
-q,--quality: Quality level (default: 0)-a,--abundance: Abundance percentage for mine/well resources (default: 90)-b,--building: Filter by building name-s,--search: Search resources by name (case-insensitive)-c,--contract: Direct contract mode (0% market fee, 50% transport)-r,--robots: Apply 3% wage reduction-o,--overhead: Admin overhead percentage (default: 0)-e,--no-seasonal: Exclude seasonal resources
Analyze return on investment for buildings based on their best performing resource.
Options:
-b,--building: Filter by building name-l,--level: Maximum building level (default: 20)-p,--per-step: Calculate per-upgrade-step ROI- Plus inherited:
-q,-a,-c,-r,-o,-e
Calculate lifecycle ROI for abundance resources (simulates decay from starting abundance to 85%).
Options:
-b,--building: Filter by building name-l,--level: Maximum building level (default: 20)-t,--time: Base build time in hours- Plus inherited:
-q,-a,-c,-r,-o,-e
Simulate prospecting to find target abundance.
Options:
-t,--target: Target abundance percentage (required)-d,--duration: Build time per attempt in hours (default: 12)-s,--slots: Number of building slots (default: 1)
Various debugging and diagnostic tools.
Options:
-u,--unassigned: List resources not assigned to any building
Compare selling on the market vs selling via contracts with a custom contract price. Shows side-by-side comparison with profit differences.
Options:
-s,--search: Search resources by name (case-insensitive, required)-p,--price: Contract price per unit (required, accepts floats like 97.5)- Plus inherited:
-q,-a,-r,-o,-e
Use a genetic algorithm to find the optimal building configuration for maximum profit within a budget constraint. The algorithm simulates 48 hours of production, using company inventory for inputs when available and buying missing inputs from the market. At the end, all inventory is sold with market fees and transportation costs applied.
Options:
-s,--slots: Number of building slots available (default: 5)-b,--budget: Maximum investment budget for all buildings (default: 100000)-p,--population: Population size for the genetic algorithm (default: 50)-g,--generations: Number of generations to evolve (default: 100)-m,--mutation-rate: Probability of mutation 0.0-1.0 (default: 0.1)-x,--crossover-rate: Probability of crossover 0.0-1.0 (default: 0.7)-l,--max-level: Maximum building level allowed (default: 10)-t,--tournament-size: Tournament size for selection (default: 3)--elitism: Number of best individuals to preserve each generation (default: 2)--budget-penalty: Penalty factor for exceeding budget (default: 2.0)- Plus inherited:
-q,-a,-r,-o,-e
Analyze a player's company setup and provide upgrade recommendations based on marginal ROI.
Options:
-u,--user-id: User ID to fetch company data for (required)-n,--top-n: Number of upgrade recommendations to show (default: 10)- Plus inherited:
-q,-a,-c,-r,-o,-e
View top 30 most profitable quality 0 resources with 85% abundance:
uv run main.py profit -a 85
# or without subcommand (defaults to profit):
uv run main.py -a 85Calculate profits for Quality 2 resources:
uv run main.py profit -q 2Search for "Electric" and "Water" related resources at Quality 1:
uv run main.py profit -s Electric Water -q 1Filter by building (e.g., Farm) to see its production profits:
uv run main.py profit -b FarmCalculate direct contract profits (0% fee, 50% transport):
uv run main.py profit -c
# or with building filter:
uv run main.py profit -b Farm -cExclude seasonal resources from calculations:
uv run main.py profit -eBuilding ROI analysis:
# ROI for all buildings
uv run main.py roi
# ROI for specific building
uv run main.py roi -b Farm
# ROI with level-by-level breakdown
uv run main.py roi -b Mine -l 15 --per-stepSimulate prospecting for 95% abundance with 12h build time:
uv run main.py prospect -t 95 -d 12Simulate prospecting with 3 parallel slots:
uv run main.py prospect -t 98 -d 12 -s 3Find the optimal building level for a Mine starting at 95% abundance:
uv run main.py lifecycle -a 95 -b Mine -t 2Debug: List unassigned resources:
uv run main.py debug -uCompare selling "Steel" on market vs contract at $97 per unit:
uv run main.py compare -s steel -p 97Compare with quality 3 and 95% abundance:
uv run main.py compare -s "crude oil" -p 150.50 -q 3 -a 95Compare multiple resources at once:
uv run main.py compare -s steel iron -p 50Compare with robots and admin overhead:
uv run main.py compare -s steel -p 97 -r -o 5Run genetic algorithm optimization with 5 slots and $500,000 budget:
uv run main.py genetic -s 5 -b 500000Run genetic algorithm with custom parameters:
uv run main.py genetic -s 3 -b 100000 -p 50 -g 100 -l 10 -m 0.15Run a quick genetic optimization with fewer generations:
uv run main.py genetic -s 5 -b 200000 -g 30 -p 20For ease of migration, the tool supports running without specifying a subcommand. When no subcommand is provided, it defaults to the profit command. Additionally, common flags (-q, -a, -c, -r, -o, -b, -s, -e) are available at the top level for backwards compatibility:
# These are equivalent:
uv run main.py -a 85
uv run main.py profit -a 85However, using the explicit subcommand structure is recommended for clarity and to access all command-specific options.
The tool displays a formatted table using rich with the following columns:
- Resource: Name of the produced item (bold white). A yellow
(*)indicates it is an abundance-based resource (Mine/Well). - Profit/hr: Net profit per hour. Highlighted in green if positive and red if negative.
- Revenue/hr: Gross income per hour from sales (white).
- Fee/hr: 4% market exchange fee (red).
- Costs/hr: Combined cost of wages (including admin overhead) and input materials (yellow).
- Transp/hr: Total transportation costs (magenta). A red
(!)indicates missing input prices.
- Yellow (*): Indicates abundance-based resource (e.g., Bauxite, Crude oil, etc.). The production rate is multiplied by the abundance percentage.
- Red (!): Indicates that one or more input materials for that resource do not have a market price at the specified quality level, which may result in inaccurate profit calculations.
If the -R or --roi flag is used, a second table is displayed showing:
- Building: The name of the building.
- Best Resource: The resource produced by that building which yields the highest hourly profit.
- Building Cost: Total construction cost using current Q0 market prices.
- Daily Profit: Estimated daily profit from producing the best resource (24 hours).
- ROI (Daily): Return on Investment per day as a percentage.
- Break Even: Estimated number of days to recover the construction cost.
Displays a simulation of the building's entire useful life from starting abundance down to 85%:
- Resource: The resource being produced.
- Level: Building level being simulated.
- Build(h): Total time spent on construction and upgrades (hours). Abundance decays during this period.
- Prod Days: Total days of active production until abundance hits 85%.
- Investment: Total cash spent on construction and upgrades.
- Unrecoverable: The net loss on building materials when scrapping (50% loss for Level 3+).
- Ops Profit: Total profit from production over the building's life.
- Net Profit:
Ops Profit - Unrecoverable. This is the primary metric for choosing the best upgrade level.
Level-based ROI Analysis (when using --roi and --building):
If the -B or --building flag is used along with -R, the ROI analysis will show levels from 1 up to --max-level (default 20) for the filtered building. This helps visualize how profit and investment scale as the building is leveled up.
When using the -P or --prospect flag, the tool displays:
- Prospecting Simulation Results:
- Target Abundance: The percentage you are aiming for.
- Probability of Success: The chance of hitting the target in a single attempt.
- Expected Attempts: The average number of attempts needed (1/p).
- Expected Time: The average time required to hit the target.
- Days until 85%: If target > 85%, shows estimated days until abundance decays to 85% (at 0.032% daily decay).
- Confidence Intervals (Time to Success):
- Shows the number of attempts and total time required to be X% sure (50%, 80%, 90%, 95%, 99%) of having found the target abundance.
When using the compare command, the tool displays a side-by-side comparison:
Market columns:
- Mkt Price: Market price from VWAP at the specified quality
- Mkt Fee/u: Market fee per unit (4% of price)
- Mkt Trans/u: Transport cost per unit (100% rate)
- Mkt Net/u: Net profit per unit after all costs
- Mkt $/hr: Total profit per hour
Contract columns:
- Cnt Price: User-defined contract price per unit
- Cnt Fee/u: Market fee per unit (always $0.00 for contracts)
- Cnt Trans/u: Transport cost per unit (50% rate)
- Cnt Net/u: Net profit per unit after all costs
- Cnt $/hr: Total profit per hour
Difference columns:
- Diff/u: Difference in net profit per unit (Contract - Market). Green if contract is better, red if worse.
- Diff/hr: Difference in profit per hour (Contract - Market). Green if contract is better, red if worse.
When using the genetic command, the tool displays:
Configuration Summary:
- Shows all parameters used for the genetic algorithm run including slots, budget, population size, generations, and rates.
Best Building Configuration:
- A table showing the optimal buildings found, their levels, and individual costs.
Results Summary:
- Total Investment: Combined cost of all buildings in the configuration.
- Budget Status: Whether the configuration is WITHIN or OVER the specified budget.
- Buildings Used: Number of building slots utilized out of total available.
- 48-Hour Profit: Net profit from the simulated 48-hour production period.
- Hourly/Daily Profit: Calculated average profit rates.
- ROI Break-even: Days to recover the building investment from profits.
Fitness Evolution Graph:
- An ASCII graph showing how the best fitness improved over generations.
- Use this to determine if more generations or larger population would help.
- A flat line at the end suggests convergence; a still-rising line suggests more generations could improve results.
resources.json: Contains raw metadata for all resources (wages, inputs, production rates). Generated from API.vwaps.json: Contains the latest market Volume Weighted Average Prices for all resources and qualities. Generated from API.simtools/data/abundance_resources.json: List of resources that use the abundance calculation.simtools/data/seasonal_resources.json: List of resources that are considered seasonal and can be excluded.simtools/data/buildings.json: Contains metadata for buildings, including construction costs and the resources they produce.
The package can also be imported for programmatic use:
from simtools import Resource, Building, SimcoAPI
from simtools.calculator import (
calculate_all_profits,
ProfitConfig,
find_best_resource_profit,
calculate_total_investment,
)
# Fetch data
api = SimcoAPI(realm=0)
resources_data = api.get_resources()
vwaps = api.get_market_vwaps()
# Create resource objects
resources = [Resource.from_api_data(r) for r in resources_data["resources"]]
# Load buildings
buildings = Building.load_all()
# Calculate profits
config = ProfitConfig(quality=0, abundance=90.0)
profits = calculate_all_profits(resources, price_map, transport_price, config)
# Find best resource for a building
building_resources = [r for r in resources if r.building_name == "Mine"]
best_resource, profit_data = find_best_resource_profit(
building_resources, price_map, transport_price, config
)
# Calculate total investment for a building at level 5
building = buildings[0]
total_cost, missing = calculate_total_investment(building, 5, q0_prices, name_to_id)