← back to Zero Code Trading Bot

scripts/new_bot.py

72 lines

#!/usr/bin/env python3
"""
new_bot.py — scaffold a new paper-first bot project from the template.

    scripts/new_bot.py <bot-name> [--dest DIR] [--strategy path/to/strategy.json]

Copies assets/bot-template/ into DIR/<bot-name>/ (default DIR=~/Projects), drops
in a compiled strategy.json if one is provided (else the longshot-fade example),
git-inits the new project, and prints next steps. Never runs the bot; never
touches live keys.
"""

import argparse
import json
import os
import shutil
import subprocess
import sys

SKILL_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATE = os.path.join(SKILL_ROOT, "assets", "bot-template")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("name", help="bot project name (kebab-case)")
    ap.add_argument("--dest", default=os.path.expanduser("~/Projects"))
    ap.add_argument("--strategy", help="path to a strategy.json to inject")
    ap.add_argument("--no-git", action="store_true")
    args = ap.parse_args()

    dest = os.path.join(args.dest, args.name)
    if os.path.exists(dest):
        sys.exit(f"refusing to overwrite existing path: {dest}")
    shutil.copytree(TEMPLATE, dest)

    if args.strategy:
        with open(args.strategy) as f:
            strat = json.load(f)
        strat.setdefault("name", args.name)
        strat["mode"] = "paper"  # always scaffold in paper mode, no exceptions
        with open(os.path.join(dest, "strategy.json"), "w") as f:
            json.dump(strat, f, indent=2)

    # data/ is created on first fill; add a keep + gitignore for the ledger.
    os.makedirs(os.path.join(dest, "data"), exist_ok=True)
    with open(os.path.join(dest, ".gitignore"), "w") as f:
        f.write("data/ledger.jsonl\ndata/LIVE_CONFIRMED\ndata/KILL\n.env\n__pycache__/\n")

    if not args.no_git:
        try:
            subprocess.run(["git", "init", "-q"], cwd=dest, check=True)
            subprocess.run(["git", "add", "-A"], cwd=dest, check=True)
            subprocess.run(
                ["git", "-c", "user.email=steve@designerwallcoverings.com",
                 "-c", "user.name=Steve", "commit", "-q", "-m",
                 f"scaffold {args.name} paper bot"], cwd=dest, check=True)
        except (subprocess.CalledProcessError, FileNotFoundError) as e:
            print(f"  (git init skipped: {e})")

    print(f"✅ scaffolded paper bot → {dest}")
    print("   next:")
    print(f"     cd {dest}")
    print("     python venue_adapter.py         # confirm live market data ($0)")
    print("     python bot.py --once --dry-run   # decide, place no fills")
    print("     python bot.py --once             # first paper fills")
    print("     python dashboard.py --serve      # watch paper P&L")


if __name__ == "__main__":
    main()