# Build a Trading Bot

Build a bot that trades BTC 15-minute prediction markets on Turbine using Claude Code. This guide covers wallet setup, funding, bot generation via the `/market-maker` skill, and cloud deployment.

BTC Quick Markets ask "Will BTC be above $X in 15 minutes?" — a new market rotates in every 15 minutes. Your bot detects each transition and moves to the new market automatically.

## Prerequisites

* **Python 3.9+** and **pip**
* **Git**
* **Claude Code CLI** — install with `npm install -g @anthropic-ai/claude-code`
* A terminal (macOS, Linux, or WSL)

## Create a Wallet

Your bot signs orders with a raw private key. Use a **dedicated wallet** — not your main wallet.

### Export from MetaMask

1. Open MetaMask and select the account you want to use
2. Click the three dots next to the account name
3. Go to **Account Details** > **Show Private Key**
4. Enter your password and copy the hex string (starts with `0x`)

### Generate a New Wallet

Using Python:

```python
from eth_account import Account
acct = Account.create()
print(f"Address:     {acct.address}")
print(f"Private Key: {acct.key.hex()}")
```

Or using Foundry's `cast`:

```bash
cast wallet new
```

Save the private key. You will need it when the `/market-maker` skill prompts you.

{% hint style="warning" %}
Never share your private key or commit it to version control. Use a wallet with only the funds you intend to trade.
{% endhint %}

## Fund Your Wallet with USDC

Your bot needs USDC on **Polygon** (chain ID `137`) to place orders. $10 is enough to start.

No MATIC is required. All Turbine operations — USDC approval, order signing, position claiming — are gasless.

### Bridge from Another Chain

If you already hold USDC on Ethereum, Arbitrum, or another chain:

* [Polygon Bridge](https://portal.polygon.technology/bridge) — official Polygon bridge
* [Jumper Exchange](https://jumper.exchange/) — cross-chain swap aggregator

### Buy and Withdraw from an Exchange

1. Purchase USDC on Coinbase, Binance, Kraken, or any exchange that supports Polygon withdrawals
2. Withdraw USDC to your wallet address on the **Polygon** network (chain ID `137`)

### Verify

USDC contract on Polygon: `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359`

Check your balance on [Polygonscan](https://polygonscan.com/) or in MetaMask after adding the Polygon network:

| Parameter       | Value                     |
| --------------- | ------------------------- |
| Network Name    | Polygon                   |
| RPC URL         | `https://polygon-rpc.com` |
| Chain ID        | `137`                     |
| Currency Symbol | `MATIC`                   |
| Block Explorer  | `https://polygonscan.com` |

## One-Line Install

Run a single command to clone the SDK, install dependencies, create a `.env` template, and launch Claude Code with the bot generator:

```bash
curl -sSL turbinefi.com/claude | bash
```

This executes `scripts/create-bot.sh`, which does the following:

{% stepper %}
{% step %}

### Clone the SDK

Clones [turbine-py-client](https://github.com/ojo-network/turbine-py-client) into a `turbine-bot/` directory.
{% endstep %}

{% step %}

### Install dependencies

Runs `pip install -e .` to install the SDK and its dependencies (`eth-account`, `httpx`, `web3`, `pynacl`, etc.).
{% endstep %}

{% step %}

### Create environment template & launch generator

Creates a `.env` file from the template and runs `claude "/market-maker"` to start the interactive bot generator.
{% endstep %}
{% endstepper %}

{% tabs %}
{% tab title="One-liner" %}

```bash
curl -sSL turbinefi.com/claude | bash
```

{% endtab %}

{% tab title="Manual" %}

```bash
git clone https://github.com/ojo-network/turbine-py-client.git turbine-bot
cd turbine-bot
pip install -e .
cp .env.example .env
claude "/market-maker"
```

{% endtab %}
{% endtabs %}

## The `/market-maker` Skill Flow

The skill walks through four steps interactively.

### Private Key

Claude asks for your Ethereum private key and writes it to `.env`:

```
TURBINE_PRIVATE_KEY=0xYourPrivateKeyHere
```

If `.env` already contains a key, this step is skipped.

### API Credentials

API credentials are **not configured during the skill** — they are registered automatically when the bot runs for the first time. The SDK calls `TurbineClient.request_api_credentials()`, which signs a message with your wallet to prove ownership and receives Ed25519 API keys. These are saved to `.env` so subsequent runs reuse them:

```
TURBINE_API_KEY_ID=abc123...
TURBINE_API_PRIVATE_KEY=base64encodedkey...
```

### Algorithm Selection

Claude presents six algorithm choices:

| Algorithm                | How It Works                                                                                                                                                   | Risk   |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| **Price Action**         | Fetches live BTC price from Pyth Network and compares to the market strike price. BTC above strike = buy YES, below = buy NO. Confidence scales with distance. | Medium |
| **Simple Spread**        | Places symmetric bid/ask orders around the current mid-price with a fixed spread.                                                                              | Medium |
| **Inventory-Aware**      | Like Simple Spread, but skews quotes to reduce accumulated position.                                                                                           | Lower  |
| **Momentum**             | Detects price direction from recent trades. Buys with the trend.                                                                                               | Higher |
| **Mean Reversion**       | Fades large price moves, betting on reversion to the mean.                                                                                                     | Higher |
| **Probability-Weighted** | Bets that prices far from `500000` ($0.50) will revert toward 50%.                                                                                             | Medium |

**Price Action is recommended for BTC Quick Markets.** It uses the Pyth Network oracle — the same data source Turbine uses to resolve markets — so the bot's signal is directly aligned with the resolution mechanism.

### Bot Generation

Claude generates a complete Python file (e.g., `price_action_bot.py`) based on your algorithm choice. The generated code follows the structure of `examples/price_action_bot.py`, the SDK's reference implementation. It includes all the patterns described in the next section.

## What the Bot Does

The generated bot handles the full trading lifecycle. The lifecycle is summarized below.

{% stepper %}
{% step %}

### Startup

* Loads `TURBINE_PRIVATE_KEY` from `.env`
* Checks for existing API credentials in `.env` — if missing, calls `TurbineClient.request_api_credentials()` to register and saves them automatically
* Initializes `TurbineClient` with `host="https://api.turbinefi.com"` and `chain_id=137`
  {% endstep %}

{% step %}

### First trade on a new market

* Signs a gasless EIP-2612 max USDC permit for the settlement contract (`approve_usdc_for_settlement()`). This is a one-time operation per settlement contract — all future orders on that contract reuse the existing allowance with no per-order permit overhead.
  {% endstep %}

{% step %}

### Each cycle (every \~10 seconds)

* Fetches the active BTC Quick Market via `get_quick_market("BTC")` — returns the market ID, strike price, and expiration time
* Fetches the current BTC price from Pyth Network (feed `0xe62df6c8...`)
* Runs the algorithm's signal logic (e.g., Price Action compares BTC price to strike)
* Places a limit order if the signal has sufficient confidence — `post_order()` with the computed price (`0`–`999999`, where `500000` = $0.50) and size in shares (6 decimals, e.g., `1000000` = 1 share)
* Tracks positions in USDC terms and respects `--max-position`
  {% endstep %}

{% step %}

### Market transitions

* Detects when the current market is expiring (< 60 seconds remaining)
* Cancels open orders on the expiring market
* Fetches the next BTC Quick Market and resumes trading
  {% endstep %}

{% step %}

### Background tasks

* Claims winnings from resolved markets via `claim_winnings()` (gasless, relayer-submitted)
* Syncs positions from the API periodically
  {% endstep %}

{% step %}

### Shutdown (Ctrl+C)

* Cancels all open orders and exits cleanly
  {% endstep %}
  {% endstepper %}

## Run Your Bot

Set the chain and host, then run the generated bot file:

```bash
CHAIN_ID=137 TURBINE_HOST=https://api.turbinefi.com python price_action_bot.py
```

Or use the reference implementation directly:

```bash
CHAIN_ID=137 TURBINE_HOST=https://api.turbinefi.com python examples/price_action_bot.py \
    --order-size 1 \
    --max-position 10
```

### Parameters

| Flag             | Description                      | Default |
| ---------------- | -------------------------------- | ------- |
| `--order-size`   | USDC amount per order            | `1.0`   |
| `--max-position` | Maximum USDC exposure per market | `10.0`  |

### Environment Variables

| Variable                  | Description                                              | Required                          |
| ------------------------- | -------------------------------------------------------- | --------------------------------- |
| `TURBINE_PRIVATE_KEY`     | Wallet private key (hex, `0x`-prefixed)                  | Yes                               |
| `TURBINE_API_KEY_ID`      | Ed25519 API key ID (auto-registered on first run)        | No                                |
| `TURBINE_API_PRIVATE_KEY` | Ed25519 API private key (auto-registered on first run)   | No                                |
| `CHAIN_ID`                | Blockchain chain ID                                      | Yes (`137` for Polygon)           |
| `TURBINE_HOST`            | API server URL                                           | Yes (`https://api.turbinefi.com`) |
| `CLAIM_ONLY_MODE`         | Set to `true` to disable trading and only claim winnings | No                                |

### Expected Output

```
Registering new API credentials...
API credentials registered and saved to .env
Starting Price Action Bot...
  Chain: Polygon (137)
  Order size: $1.00 USDC
  Max position: $10.00 USDC
Approving USDC for settlement (gasless)...
USDC approved via gasless max permit
Fetched BTC Quick Market: Will BTC be above $97,432.15 in 15 minutes?
  Market ID: 0xabc123...
  Expires in: 12m 30s
BTC Price: $97,489.22 (above strike by 0.06%)
  Signal: BUY YES (confidence: 0.58)
  Placed order: BUY 1.72 YES @ 580000 ($0.58)
Market transition detected — switching to new market...
Claimed winnings from resolved market: +$1.72 USDC
```

Press `Ctrl+C` to stop. The bot cancels all open orders before exiting.

## Deploy on Railway

[Railway](https://railway.com/) runs your bot 24/7 in the cloud. The free tier includes $5 credit for 30 days.

### Using the `/railway-deploy` Skill

From your bot directory:

```bash
claude "/railway-deploy"
```

The skill:

1. Checks for the Railway CLI and installs it if missing (`brew install railway`, `npm i -g @railway/cli`, or the shell installer)
2. Identifies your bot file (looks for `*bot*`, `*trader*`, `*maker*` patterns in the project root)
3. Generates deployment files:
   * `requirements.txt` — contains `.` to install from `pyproject.toml`
   * `main.py` — entry point that runs your bot file
   * `railway.toml` — restart policy configuration
4. Runs `railway login` to authenticate
5. Pushes environment variables (`TURBINE_PRIVATE_KEY`, `TURBINE_API_KEY_ID`, `TURBINE_API_PRIVATE_KEY`, `CHAIN_ID`, `TURBINE_HOST`)
6. Deploys with `railway up --detach`

### Manual Deployment

```bash
# Install Railway CLI
npm i -g @railway/cli

# Authenticate
railway login

# Create a new project
railway init

# Push environment variables
railway variables set TURBINE_PRIVATE_KEY=0x...
railway variables set TURBINE_API_KEY_ID=your_key_id
railway variables set TURBINE_API_PRIVATE_KEY=your_api_key
railway variables set CHAIN_ID=137
railway variables set TURBINE_HOST=https://api.turbinefi.com

# Deploy
railway up --detach
```

### Monitoring

```bash
# Stream logs
railway logs

# Check deployment status
railway status
```
