autotrade
A paper-trading experiment on Indian equities (Nifty 500). Claude itself runs the trading loop on a free GCP VM and edits its own strategy between polls. Real Indian transaction costs (STT, GST, stamp duty, brokerage), real Kite Connect price feed, no real money.
Status: paused. Two-week run ended May 8 2026 at Rs 108,049 (+8.05% on Rs 1,00,000 starting capital). The repo is left in a state forkable for anyone who wants to continue or reuse the harness. The full writeup (sessions, incidents, what the experiment actually taught) is at https://www.akashtandon.in/autotrader/.
What's in here
live.py- single-shot polling loop. Fetches prices, runs strategy, executes paper trades, persists state.strategy.py- trading signals + position sizing. The only file the agent is allowed to edit.prepare.py- shared types (Signal,Position,Trade,Portfolio) and the Indian-equity cost calculator.config.py- starting balance, Nifty 500 universe, polling config, cost rates.kite_fetch.py/kite_login.py- Kite Connect data layer + daily OAuth helper.corporate_actions.py- NSE ex-date blocklist + demerger entitlement minting.program.md- full instructions for the trading agent.VM_LOOP_PROMPT.md- the prompt Claude runs under/loop 5mon the VM.DEPLOY.md- end-to-end VM setup guide (GCP e2-micro, free tier).learnings.md- the original run's journal. Treat as historical; reset for your own run.
Quick start (local)
One-time prerequisites (you do these, not Claude Code)
- Get Zerodha Kite Connect credentials. Sign up at https://developers.kite.trade, create an app, note the API key and API secret. Kite Connect costs Rs 500/month for real-time NSE quotes.
- Clone your fork and bootstrap the environment.
git clone https://github.com/<your-username>/autotrade.git cd autotrade python3 -m venv .venv && source .venv/bin/activate pip install -r requirements.txt cp .env.example .env # Edit .env: set KITE_API_KEY and KITE_API_SECRET from step 1.
- Complete the daily Zerodha OAuth flow. Zerodha forbids scripted login, so this is manual:
Open the printed URL in a browser. Log in to Zerodha. After login, your browser will get redirected to a URL that starts with
http://127.0.0.1/...&request_token=...- the page won't load, but copy the full URL from the address bar. Then:python kite_login.py '<paste the full redirect URL here>'.kite_tokenis now seeded. You'll repeat this once per day (token expires near 6 AM IST).
Running it with Claude Code locally
Open Claude Code in this directory: claude (after source .venv/bin/activate). Then ask it to run one poll:
Read program.md for context, then run `python live.py` and tell me what happened.
Per-poll, Claude should:
- Run
python live.py(must be inside the activated venv, with a fresh.kite_token). - Read the output - portfolio snapshot, signals generated, trades executed.
- Decide whether to edit
strategy.py. Criteria are inVM_LOOP_PROMPT.mdunder "Criteria for Strategy Changes". Don't thrash - only edit on clear evidence across multiple polls. - If changing strategy: edit
strategy.py, commit withstrategy:prefix, append a note tolearnings.mdexplaining why.
For continuous polling, use Claude Code's /loop 5m command and point it at VM_LOOP_PROMPT.md:
/loop 5m Follow VM_LOOP_PROMPT.md. Keep each iteration brief.
Expected output
- Outside market hours (Mon-Fri 9:15-15:30 IST):
live.pyearly-returns with a "MARKET CLOSED" / "outside market hours" line and does not fetch prices or update state. - Inside market hours, first poll:
live_state.jsonis created; portfolio starts at Rs 1,00,000 cash, no positions; signals may or may not fire depending on the universe state. - Inside market hours, subsequent polls: state is loaded from
live_state.json, prices refetched, strategy run, trades executed if signals fire.live.pyenforces a minimum poll interval (config.POLL_INTERVAL_MINUTES, default 4 minutes) and skips early calls with a "Skipping" message. - Auth failure:
live.pyraises a clear error if.kite_tokenis missing or expired. Re-run the OAuth flow above.
Resetting
live_state.json, results.tsv, and logs/ are gitignored and start fresh on first run. To reset between experiments: rm live_state.json (next poll begins from Rs 1,00,000 again).
Running it autonomously on a VM
Read DEPLOY.md. The short version: free-tier GCP e2-micro + Ubuntu 24.04 + tmux + Claude Code's /loop 5m driving the observe-iterate-commit cycle. The agent edits strategy.py, commits, pushes; the next poll picks up the new code via hot-reload.
Cost: ~Rs 500/month for Kite Connect data. The VM is free. Claude Code usage is whatever your plan covers.
Forking and continuing
If you want to pick up where this left off, or run your own variant:
- Fork the repo, clone your fork.
learnings.mdis the original run's journal. Optionally archive and clear it before starting your own;live_state.json,results.tsv, and the daily logs are gitignored and will start fresh.- Follow
DEPLOY.mdfor the VM, or just run locally withpython live.py. - Read
program.mdfor the trading-agent contract andCLAUDE.mdfor what Claude should and shouldn't edit.
Known issues (what the original run did not solve)
- Loop liveness. The
/loop-driven tmux session died silently twice during the run (May 5, May 7). No watchdog. A cron that pings the latest log file's mtime and alerts on staleness would close this. - No bid/ask in the simulator. Paper fills assume the observed quote. Slippage, spread, partial fills, and market impact are not modeled.
- Latency. A 5-minute polling cadence is coarse for momentum trades.
- Stale-price defenses are heuristic. The ex-date blocklist and market-state guard cover the bugs the original run hit, not the ones it didn't.
Constraints baked into the system
- Loss floor at Rs 80,000 - portfolio below this triggers full liquidation.
- No short selling, no leverage. Sell only shares held, buy only with available cash.
- Real Indian equity delivery costs apply.
- The agent may only edit
strategy.py. Everything else is off-limits.
License
MIT. See LICENSE.

























