Skip to content

Automatically prices items using listing data from backpack.tf, with data from prices.tf acting as a baseline.

License

Notifications You must be signed in to change notification settings

TF2-Price-DB/bliss-autopricer

 
 

Repository files navigation

bliss-autopricer

npm version Node.js PostgreSQL ESLint Prettier License: MIT

logo

A custom pricer that generates item prices by analysing live and snapshot data from backpack.tf, applies sanity checks, and integrates seamlessly with TF2 Autobot. Modified and forked from Jack's Auto Pricer!


Features

  • Automated Pricing: Generates item prices using real-time and snapshot backpack.tf listing data, ensuring a profit margin and performing various sanity checks.
  • Robust Fallback Pricing: If an item cannot be priced from listings, the pricer will attempt to fetch and convert Steam Community Market (SCM) prices (with configurable margin and rounding), and only fall back to Backpack.tf (BPTF) prices as a last resort. This fallback system supports all item types, including unusuals, killstreakers, and special attributes.
  • Baseline Comparison: Compares generated prices against Prices.tf and disregards prices that exceed configured percentage thresholds.
  • Trusted/Blacklisted Steam IDs: Prioritises listings from trusted bots and filters out untrusted bots when calculating prices. Fully configurable.
  • Excluded Listing Descriptions: Filters out listings with descriptions containing configured keywords (e.g., spells).
  • Outlier Filtering: Removes listings with prices that deviate too much from the average.
  • API Functionality: Add/delete items for auto-pricing and retrieve prices via the API.
  • Socket.IO Server: Emits item prices to listeners in a format compatible with TF2 Auto Bot.
  • Price Watcher Web Interface: Dashboard to monitor item data freshness, view outdated entries, and manage your bot's selling pricelist.

Pricing Logic & Fallback System

The pricer uses a robust multi-stage fallback system to ensure all items (including rare, unusual, and illiquid items) are priced as reliably as possible:

  1. Own Listings: Attempt to price using live buy/sell listings from trusted sources.
  2. Steam Community Market (SCM) Fallback: If not enough listings are available, the pricer fetches the item's SCM price, converts it to keys/metal (using the current key price), applies configurable margins (scmMarginBuy, scmMarginSell), and always rounds to the nearest scrap. This fallback is robust for all item types, including unusuals, killstreakers, australium, and special attributes.
  3. Backpack.tf (BPTF) Fallback: If SCM pricing is unavailable, the pricer falls back to BPTF prices as a last resort.
  • Batching & Rate Limiting: SCM fallback requests are batched and rate-limited using p-limit to avoid Steam rate limits and ensure stability, even with large numbers of unpriced items.
  • Rounding: All fallback prices (SCM or BPTF) are always rounded to the nearest scrap for consistency.
  • Source: All fallback prices use source: 'bptf' for compatibility with TF2Autobot and other bots.

Requirements

  • Node.js (v18 or newer)
  • npm
  • PostgreSQL (v12 or newer)
  • TF2 Auto Bot

Setup & Installation

1. Clone and Install Dependencies

git clone https://github.com/OliverPerring/bliss-autopricer.git
cd bliss-autopricer
npm install

2. Configure Application

Copy and configure both config.json and pricerConfig.json at the project root.
See the Configuration section below for details.


PostgreSQL Setup

1. Install PostgreSQL

  • Download and install from postgresql.org.
  • Ensure the PostgreSQL service is running.

2. Create Database and Schema

Open a terminal and run:

psql -U postgres

Then, in the psql prompt:

CREATE DATABASE "bptf-autopricer";
\c bptf-autopricer
CREATE SCHEMA tf2 AUTHORIZATION postgres;

3. Create Tables

You can use the provided initialize-db.sql:

psql -U postgres -d bptf-autopricer -f initialize-db.sql

Or run the following SQL manually:

CREATE TABLE tf2.listings (
  name character varying NOT NULL,
  sku character varying NOT NULL,
  currencies json NOT NULL,
  intent character varying NOT NULL,
  updated bigint NOT NULL,
  steamid character varying NOT NULL,
  PRIMARY KEY (name, sku, intent, steamid)
);

CREATE TABLE tf2.key_prices (
  id SERIAL PRIMARY KEY,
  sku TEXT NOT NULL,
  buy_price_metal DECIMAL NOT NULL,
  sell_price_metal DECIMAL NOT NULL,
  timestamp INT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE tf2.listing_stats (
  sku TEXT PRIMARY KEY,
  current_count INTEGER DEFAULT 0,
  moving_avg_count REAL DEFAULT 0,
  last_updated TIMESTAMP DEFAULT NOW (),
  current_buy_count integer DEFAULT 0,
  moving_avg_buy_count real DEFAULT 0,
  current_sell_count integer DEFAULT 0,
  moving_avg_sell_count real DEFAULT 0
);

CREATE TABLE tf2.price_history (
  sku TEXT NOT NULL,
  buy_metal NUMERIC NOT NULL,
  sell_metal NUMERIC NOT NULL,
  timestamp TIMESTAMP NOT NULL DEFAULT NOW ()
);

4. Test Database Connection and Permissions

In psql, run:

\dt tf2.*

You should see the three tables listed.
Test permissions by inserting a test row (replace values as needed):

INSERT INTO
  tf2.listings (name, sku, currencies, intent, updated, steamid)
VALUES
  (
    'Test Item',
    '123;6',
    '{"keys":1,"metal":10}',
    'buy',
    1700000000,
    '12345678901234567'
  );

If you get no errors, your user has the correct permissions.


Configuration

config.json

Holds core pricer settings:

{
  "bptfAPIKey": "<your backpack.tf API key>",
  "bptfToken": "<your backpack.tf token>",
  "steamAPIKey": "<your Steam API key>",
  "database": {
    "schema": "tf2",
    "host": "localhost",
    "port": 5432,
    "name": "bptf-autopricer",
    "user": "postgres",
    "password": "<db password>"
  },
  "pricerPort": 3456,
  "maxPercentageDifferences": {
    "buy": 5,
    "sell": -8
  },
  "alwaysQuerySnapshotAPI": true,
  "fallbackOntoPricesTf": false,
  "excludedSteamIDs": ["76561199384015307", "..."],
  "trustedSteamIDs": ["76561199110778355", "..."],
  "excludedListingDescriptions": ["exorcism", "spell", "spelled"],
  "blockedAttributes": {
    "Australium Gold": 15185211,
    "Team Spirit": 12073019,
    "..."
  },
  "scmMarginBuy": 0.05, // (optional) Margin to subtract from SCM price when buying (e.g., 0.05 = 5% below SCM)
  "scmMarginSell": 0.05 // (optional) Margin to add to SCM price when selling (e.g., 0.05 = 5% above SCM)
}
  • scmMarginBuy and scmMarginSell control the buy/sell margins applied to fallback SCM prices. If omitted, margins default to 0 (no adjustment).
  • All fallback prices are always rounded to the nearest scrap for consistency.
  • See the Pricing Logic & Fallback System section for details.

pricerConfig.json

Controls the Price Watcher web UI and integration with TF2AutoBot's selling pricelist:

{
  "pm2ProcessName": "tf2autobot",
  "tf2AutobotDir": "../../tf2autobot-5.13.0",
  "botTradingDir": "files/bot",
  "port": 3000,
  "ageThresholdSec": 7200
}

API Routes & Socket.IO

The Socket.IO server emits events called price with an item object as the value.
The item objects are structured as follows:

{
  "name": "Strange Australium Minigun",
  "sku": "202;11;australium",
  "source": "bptf",
  "time": 1700403492,
  "buy": { "keys": 25, "metal": 21.33 },
  "sell": { "keys": 26, "metal": 61.77 }
}

This format is compatible with TF2 Auto Bot custom pricer interface.

Example API Endpoints

  • GET /items/:sku — Retrieve a particular item object from the pricelist.
  • GET /items/ — Retrieve the entire pricelist.
  • POST /items/:sku — Endpoint for integration with TF2 Auto Bot.
  • POST /items/add/:name — Add an item to be auto-priced.
  • POST /items/delete/:name — Remove an item from auto-pricing.

See the full API documentation in this README for request/response details.


Running

Start the pricer (includes API, Socket.IO & Web Interface):

node bptf-autopricer.js

Tip: Run under PM2 to keep alive:

npm install -g pm2
pm2 start bptf-autopricer.js --name bptf-autopricer

Web Interface

The bliss-autopricer includes a built-in web dashboard for managing and monitoring your pricing bot.
Visit: http://localhost:<pricerConfig.port> (default: 3000).

Main Features

  • Dashboard Overview: View and filter items by status: Outdated, Current, and Unpriced.
  • Pricelist Management: Add, remove, and edit items and bounds directly in the table.
  • Queue System: Review and apply pending actions, which will trigger a PM2 restart for changes to take effect.
  • Navigation Bar: Access price list, bounds editing, key price graphs, profit/loss, trade history, and logs.

How to Use

  1. Start the pricer (see "Running" section).
  2. Open your browser to http://localhost:<pricerConfig.port>.
  3. Interact with the dashboard to manage items and review pending actions.
  4. Explore additional pages for advanced features.

Notes

  • All changes to your bot’s pricelist are applied atomically and will trigger a PM2 restart of your TF2Autobot process.
  • The web interface reads/writes to files/item_list.json and your bot’s pricelist.json as configured in pricerConfig.json.
  • Outdated prices are detected using the ageThresholdSec setting.

Development & Code Quality

  • Linting: Uses ESLint with plugins for best practices, security, promises, imports, JSDoc, and spellchecking.
  • Formatting: Uses Prettier with plugins for SQL and package.json sorting.
  • CI: See .github/workflows/Lint and Format.yml for automated lint/format checks.

FAQ

  • How do I connect this to TF2AutoBot?
    See: jack-richards#11

  • I am getting a 429 error in the console, what does this mean?
    See: jack-richards#17

  • I am being shown 'error: relation "listings" does not exist' when running the pricer.
    See: jack-richards#14

  • Why is the pricer giving a 'Not valid JSON error'?
    Your JSON isn't valid—check that item_list.json matches this example.

  • There are loads of 'Couldn't price item' errors, is everything broken?!
    No! The pricer is protecting you by discarding prices that deviate too much from the baseline. Over time, most items will be priced and updated regularly.


Built with ❤️ for TF2 trading

About

Automatically prices items using listing data from backpack.tf, with data from prices.tf acting as a baseline.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%