Release: Show Your Bot to People

Lesson 16 of the arbitrage course, the last one. Turn the paper-trading bot into something you can show: a trade log, a report page, a README, a clean public repository with no secrets, and an honest way to talk about the results.

Lesson 16, the last lesson of the course "Build your own arbitrage bot". The bot scans, sizes trades, simulates fills, runs on paper and stops at its limits. Today you make it something other people can read, run and judge.

The head-on way

The blunt way to show a bot is a screenshot of the terminal with a green number, or a message "it made 40 dollars this week". A screenshot cannot be checked, cannot be repeated, and hides everything that matters: how many trades, how big the worst one was, what the settings were, whether it was real money.

A release answers those questions before anyone asks. It has four parts: a log, a report, a README and a repository. Each takes less than an hour.

Part 1: a log of every decision

The bot appends one line to a file for each paper trade. A line is a small JSON object. This format is called JSON Lines: one object per line, easy to append and easy to read back. Log more than the profit: the time, the pair, the size, the prices, the settings that were active. Whatever you did not log, you cannot explain later.

Part 2: a report that reads the log

A small script reads the log and prints the numbers a visitor wants first: how many trades, how many were profitable, the total, and the worst single trade. The worst trade matters as much as the total. Then the same script writes a web page.

import json, random, html

random.seed(21)
# 1. the bot appends one line per decision to trades.jsonl (here we fake 12 paper trades)
with open("trades.jsonl", "w") as f:
    for i in range(12):
        size = round(random.choice([0.5, 1.0]), 1)
        profit = round(random.gauss(0.03, 0.12) * size, 4)
        f.write(json.dumps({"n": i + 1, "pair": "BTC/USDT", "size": size, "profit": profit}) + "\n")

# 2. the report reads the log and prints the numbers a visitor wants first
trades = [json.loads(line) for line in open("trades.jsonl")]
total = sum(t["profit"] for t in trades)
wins = sum(t["profit"] > 0 for t in trades)
worst = min(t["profit"] for t in trades)
print(f"trades {len(trades)}  wins {wins}  win rate {wins/len(trades):.0%}")
print(f"total profit {total:+.4f}  worst trade {worst:+.4f}")

# 3. the same numbers as a page you can open in a browser or publish
rows = "".join(f"<tr><td>{t['n']}</td><td>{html.escape(t['pair'])}</td><td>{t['size']}</td><td>{t['profit']:+.4f}</td></tr>" for t in trades)
page = f"""<!doctype html><meta charset="utf-8"><title>Paper bot report</title>
<h1>Paper bot report</h1>
<p>Trades: {len(trades)}. Win rate: {wins/len(trades):.0%}. Total profit: {total:+.4f}. Worst trade: {worst:+.4f}.</p>
<p><b>Paper mode: no real money.</b></p>
<table border="1" cellpadding="4"><tr><th>#</th><th>pair</th><th>size</th><th>profit</th></tr>{rows}</table>"""
open("report.html", "w").write(page)
print("wrote report.html,", len(page), "bytes")

Output:

trades 12  wins 6  win rate 50%
total profit +0.0432  worst trade -0.2725
wrote report.html, 1088 bytes

Open report.html in a browser. Look at the two numbers together. Half of the trades won and the total is slightly positive, but the worst trade (−0.2725) is six times the total profit (0.0432). One bad trade erases the whole run. A single number like "profit +0.0432" would have hidden that. This is why the report prints the worst trade next to the total.

The fake trades here are random numbers, only to give the script something to read. In your bot the log comes from the paper account of lesson 12.

Part 3: a README

The README is the first page of the repository. A visitor reads it for ten seconds and decides to go on or leave. A good one has these parts, in this order:

  1. One sentence: what the bot does. "A paper-trading bot that looks for price gaps between two exchanges."
  2. A status line: "Paper mode. No real money. Not financial advice."
  3. How to run it: three commands that work on a clean machine (install, copy the example config, start).
  4. What you will see: the output of a run or a link to the report page.
  5. How it works: the stages from lesson 3, one line each.
  6. Known limits: what the paper account does not model (delay, other bots, failed legs from lesson 11). Writing these down earns more trust than hiding them.
  7. Results: the numbers from your report, with the dates and the settings.

Test the README the way a stranger would: open a new empty folder, clone the repository, follow your own steps, and fix every place where you got stuck.

Part 4: a clean public repository

Before you make a repository public, check these. A leaked key cannot be taken back.

  • No secrets. Keys, tokens and passwords are in environment variables or in a file that is listed in .gitignore, never in the code or in the config you commit. Commit a config.example.json with empty or fake values instead.
  • Search the history. If a key was ever committed, deleting it in a new commit does not remove it from the history. Create a new key at the exchange, cancel the old one, and start the public repository from a fresh history.
  • A .gitignore that excludes the log files, the virtual environment, and the config with real values.
  • A license file, so people know whether they may reuse the code.
  • Small, readable commits with messages that say what changed.

The commands, once the folder is ready:

git init
git add .
git status          # read this list: no keys, no logs
git commit -m "Paper-trading arbitrage bot: first release"

Create an empty repository on the code hosting site you use (GitHub, GitLab), then add its address as the remote and push. You can ask your agent for the exact two commands for your site, but read git status yourself before the first push.

Talking about the results

  • Say "paper" every time. Paper profit is an upper bound, because fills in the real market are worse (lesson 11).
  • Show the worst trade and the number of trades with the total.
  • Give the dates and the settings. A result without them cannot be repeated.
  • Do not call a short good run proof. Twelve trades say little. A hundred trades over different market days say more.
  • Ask for feedback in a specific way: "Which assumption in the paper account looks wrong to you?" gets better answers than "What do you think?".

Let an AI agent write and test it

A vague request:

Prepare my bot for release.

A request with checks built in:

Do these steps and show the output of each. 1. Search the whole repository, including git history, for strings that look like API keys or tokens and list every match; fix nothing yet. 2. Write report.py that reads trades.jsonl and prints trade count, wins, total profit and the worst trade, and writes report.html; on the lesson 16 sample it must print "trades 12 wins 6" and "worst trade -0.2725". 3. Write a README with the seven parts from lesson 16 and a clean-machine run section; run the commands in a new empty folder and report where they fail. 4. Write .gitignore and config.example.json. Do not push, do not create any remote repository.

Read the list from step 1 yourself. Only you decide what counts as a secret.

Your exercise

  1. Run the report code and open report.html. Compare your printed lines with the lesson.
  2. Change the seed to 22 and then 23. How much do the win rate, total profit and worst trade change? What does that say about showing one number from twelve trades?
  3. Connect your own bot: make its paper account write to trades.jsonl and run the report on real paper output.
  4. Write the README and give it to a friend who has never seen the project. Watch where they get stuck, and fix the README, not the friend.
  5. Publish the repository. Send the link to three people and ask each one the same specific question.

The end of the course, and what is next

You started with a scanner that took an hour and you finish with a bot that finds gaps, walks the order book, accounts for fees and size, expects failures, runs on paper inside its limits, trades a second strategy, and can be read and run by someone else. Real money is a separate decision: it needs a long paper run, small size, and risk limits that you trust. Take the time.

If you got stuck anywhere, the earlier lessons have the same pattern: a blunt version first, then the idea that fixes it, and a request to your agent with a check built in. Go back to the one that hurt, and repeat its exercise.