Welcome To Stockfighter
A free programming challenge. Write code to trade on a simulated stock exchange. Solve levels, beat bots, learn how markets work.
Run your own server from GitHub:
git clone https://github.com/stockfighter-game/stockfighter.git
cd stockfighter
go build -o stockfighter .
./stockfighter
The server runs on https://play.stockfightergame.com by default and includes its own dashboard.
Self-hosted mode is coming soon. For now, play on the hosted server.
Sign Up
Save this key — you need it to sign in later.
Sign In
Your API key (save this — you'll need it for every request):
What is Stockfighter?
Stockfighter gives you access to an electronic trading market that mimics real-world exchanges. You write code to solve a series of challenges in that market. Software engineering, distributed systems, and automated trading are the themes — but you don't need to know any of that to start.
Trading Levels
15 puzzle levels from "buy 100 shares" to portfolio management with adversarial bots and dark pools. Plus a 50-stock open market for free trading.
Real Matching Engine
Price/time priority orderbook. Limit, market, FOK, IOC orders. WebSocket feeds for quotes and fills.
Bot Traders
Market makers, noise traders, snipers, trend followers, front runners, whales, and spoofers.
- Learn how markets work — orderbooks, spreads, fills, and market impact become concrete when your code trades against bots that fight back.
- Practice real engineering — WebSocket streaming, rate limiting, concurrent state, unreliable networks. The later levels are distributed systems problems.
- Use your own tools — no browser IDE, no sandbox language. Write solutions in whatever you want.
- Free and open source — run the server locally or use the hosted instance. Read the source. Modify the levels. Add your own bots.
Any Language, Just HTTP
If you can make an HTTP request, you can play. Or use a generated client library for Python, Go, TypeScript, or Java.
curl -X POST "https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/orders" \
-H "X-Starfighter-Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"account":"YOUR_ACCT", "venue":"TESTEX", "symbol":"FOOBAR",
"price":5100, "qty":100, "direction":"buy", "orderType":"limit"}'
body := `{"account":"YOUR_ACCT","venue":"TESTEX","symbol":"FOOBAR",
"price":5100,"qty":100,"direction":"buy","orderType":"limit"}`
req, _ := http.NewRequest("POST", "https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/orders",
strings.NewReader(body))
req.Header.Set("X-Starfighter-Authorization", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/orders"))
.header("X-Starfighter-Authorization", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"account\":\"YOUR_ACCT\",\"venue\":\"TESTEX\",\"symbol\":\"FOOBAR\"," +
"\"price\":5100,\"qty\":100,\"direction\":\"buy\",\"orderType\":\"limit\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
const resp = await fetch("https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/orders", {
method: "POST",
headers: { "X-Starfighter-Authorization": "YOUR_API_KEY",
"Content-Type": "application/json" },
body: JSON.stringify({ account: "YOUR_ACCT", venue: "TESTEX", symbol: "FOOBAR",
price: 5100, qty: 100, direction: "buy", orderType: "limit" })
});
const order = await resp.json();
console.log(order.totalFilled); // 100
import requests
resp = requests.post("https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/orders",
headers={"X-Starfighter-Authorization": "YOUR_API_KEY"},
json={"account": "YOUR_ACCT", "venue": "TESTEX", "symbol": "FOOBAR",
"price": 5100, "qty": 100, "direction": "buy",
"orderType": "limit"})
print(resp.json()["totalFilled"]) # 100
cfg := stockfighter.NewConfiguration()
cfg.AddDefaultHeader("X-Stockfighter-Authorization", "YOUR_API_KEY")
client := stockfighter.NewAPIClient(cfg)
order := stockfighter.Order{
Account: ACCT, Venue: "TESTEX", Symbol: "FOOBAR",
Price: 5100, Qty: 100, Direction: "buy", OrderType: "limit",
}
resp, _, _ := client.TradingAPI.PlaceOrder(ctx, "TESTEX", "FOOBAR").
Order(order).Execute()
fmt.Println(resp.TotalFilled) // 100
ApiClient client = new ApiClient();
client.setBasePath("https://play.stockfightergame.com/ob/api");
client.addDefaultHeader("X-Starfighter-Authorization", "YOUR_API_KEY");
OrderRequest req = new OrderRequest()
.account("YOUR_ACCT").venue("TESTEX").symbol("FOOBAR")
.price(5100).qty(100).direction("buy").orderType("limit");
OrderResponse resp = new TradingApi(client)
.placeOrder("TESTEX", "FOOBAR", req);
System.out.println(resp.getTotalFilled()); // 100
import { TradingApi, Configuration } from "stockfighter-client";
const api = new TradingApi(new Configuration({
basePath: "https://play.stockfightergame.com/ob/api",
headers: { "X-Stockfighter-Authorization": "YOUR_API_KEY" }
}));
const order = await api.placeOrder({
venue: "TESTEX", stock: "FOOBAR",
orderRequest: { account: "YOUR_ACCT", venue: "TESTEX", symbol: "FOOBAR",
price: 5100, qty: 100, direction: "buy", orderType: "limit" }
});
console.log(order.totalFilled); // 100
import stockfighter_client as sf
config = sf.Configuration(host="https://play.stockfightergame.com/ob/api")
config.api_key["ApiKeyHeader"] = "YOUR_API_KEY"
with sf.ApiClient(config) as client:
order = sf.TradingApi(client).place_order("TESTEX", "FOOBAR",
sf.OrderRequest(account="YOUR_ACCT", venue="TESTEX", symbol="FOOBAR",
price=5100, qty=100, direction="buy", order_type="limit"))
print(order.total_filled) # 100
FAQ
Levels
Start a level with POST /ob/api/levels/:id. Solo levels give you a private venue. PvP and market levels share a venue across all players.
Connect to a server to load levels.
API Documentation
The full interactive docs are served by the Stockfighter server. Open full API docs →
Quick Reference
WebSocket Feeds
Authentication
Pass your API key in the X-Stockfighter-Authorization) header.
curl -H "X-Stockfighter-Authorization: YOUR_API_KEY" https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks
Walkthrough: First Steps
Level 1 asks you to buy 100 shares of FOOBAR on the TESTEX exchange. Here's how to solve it from scratch.
1. Register & get your API key
Go to the Home page and sign up with a username. Your API key will appear — copy and save it.
You're signed in. Your API key:
2. Start the level
curl -X POST https://play.stockfightergame.com/ob/api/levels/first_steps \
-H "X-Starfighter-Authorization: YOUR_API_KEY"
# Response includes: venue, account, stocks, instructions
The response tells you which venue and account to use. Bots start trading immediately.
3. Check the quote
curl https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/quote
# Shows bid, ask, last price, depth
Look at the ask price — that's what sellers are offering. You'll buy at or near this price.
4. Place a buy order
curl -X POST https://play.stockfightergame.com/ob/api/venues/TESTEX/stocks/FOOBAR/orders \
-H "X-Starfighter-Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account": "YOURNAME",
"venue": "TESTEX",
"symbol": "FOOBAR",
"price": 5100,
"qty": 100,
"direction": "buy",
"orderType": "limit"
}'
Prices are in cents — 5100 = $51.00. Set your price at or above the ask to fill immediately. You'll pay the ask price, not your limit.
5. Check level status
curl https://play.stockfightergame.com/ob/api/levels/first_steps \
-H "X-Starfighter-Authorization: YOUR_API_KEY"
# When status is "won", you've completed the level!
Tips
- Use
marketorderType to buy at whatever price is available (no price needed) - Use the WebSocket feed to watch fills in real time instead of polling
- The dashboard at
https://play.stockfightergame.com/shows live orderbook and position - For level 2 (Chock a Block), you need to buy 10,000 shares without moving the price too much — split into smaller orders