> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yoshi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Paper trading: simulate trades with virtual portfolios

> Create paper trading accounts, place simulated buy and sell orders, track holdings, and understand the action approval flow for safe financial operations.

Paper trading lets you simulate stock trades with virtual money. Create an account with a starting balance, buy and sell securities, and track your portfolio — all without risking real capital.

## How it works

Paper trading uses Yoshi's **action approval** model. When you create an account or place a trade, the API returns a pending action that must be approved before execution. This safety layer prevents accidental trades.

```
Create action → Pending → Approved → Executed
                   ↘ Rejected
```

## Create a paper trading account

<CodeGroup>
  ```typescript TypeScript theme={null}
  import Yoshi from "@yoshi-ai/sdk";

  const yoshi = new Yoshi();

  const result = await yoshi.paperTrading.accounts.create({
    name: "Tech Portfolio",
    starting_cash_balance: "50000", // $50,000
  });

  console.log("Action ID:", result.action_id);
  console.log("Status:", result.status);
  console.log("Approve at:", result.approval_url);
  ```

  ```python Python theme={null}
  from yoshi import Yoshi

  yoshi = Yoshi()

  result = yoshi.paper_trading.accounts.create(
      name="Tech Portfolio",
      starting_cash_balance="50000",
  )

  print(f"Action ID: {result.action_id}")
  print(f"Status: {result.status}")
  print(f"Approve at: {result.approval_url}")
  ```

  ```bash curl theme={null}
  curl -X POST https://api.yoshi.ai/paper-trading/accounts \
    -H "Authorization: Bearer yoshi_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name": "Tech Portfolio", "starting_cash_balance": "50000"}'
  ```
</CodeGroup>

The response includes an `approval_url` — open it in your Yoshi dashboard to approve the account creation.

## Place a trade

Buy stock by share quantity or dollar amount:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Buy 10 shares of AAPL
  const trade = await yoshi.paperTrading.accounts.trades.create("acc_paper123", {
    symbol: "AAPL",
    side: "buy",
    quantity: 10,
  });

  // Or buy $5,000 worth of AAPL
  const notionalTrade = await yoshi.paperTrading.accounts.trades.create(
    "acc_paper123",
    {
      symbol: "AAPL",
      side: "buy",
      notional: 5000,
    },
  );

  console.log("Approve trade:", trade.approval_url);
  ```

  ```python Python theme={null}
  # Buy 10 shares of AAPL
  trade = yoshi.paper_trading.accounts.trades.create(
      "acc_paper123",
      symbol="AAPL",
      side="buy",
      quantity=10,
  )

  # Or buy $5,000 worth of AAPL
  notional_trade = yoshi.paper_trading.accounts.trades.create(
      "acc_paper123",
      symbol="AAPL",
      side="buy",
      notional=5000,
  )

  print(f"Approve trade: {trade.approval_url}")
  ```
</CodeGroup>

<Warning>
  Provide either `quantity` or `notional`, not both. The API returns a validation error if you include both fields.
</Warning>

## Use idempotency keys

Prevent duplicate trades when retrying failed requests:

```bash theme={null}
curl -X POST https://api.yoshi.ai/paper-trading/accounts/acc_paper123/trades \
  -H "Authorization: Bearer yoshi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: trade-aapl-2026-04-10-001" \
  -d '{"symbol": "AAPL", "side": "buy", "quantity": 10}'
```

If you send the same `Idempotency-Key` again, the API returns the cached response instead of creating a duplicate trade. See [Idempotency](/concepts/idempotency) for details.

## Check the approval status

Poll the approval endpoint to track whether the action was approved:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const status = await yoshi.approvals.retrieve("thread_abc123");

  console.log("Status:", status.status); // "pending", "approved", "rejected", "executed"
  ```

  ```python Python theme={null}
  status = yoshi.approvals.retrieve("thread_abc123")

  print(f"Status: {status.status}")
  ```
</CodeGroup>

## View your portfolio

List current holdings and trade history:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Current holdings
  const holdings = await yoshi.paperTrading.accounts.holdings.list("acc_paper123");

  for (const h of holdings.holdings) {
    console.log(`${h.symbol}: ${h.quantity} shares @ $${h.institution_price}`);
  }

  // Trade history
  for await (const trade of yoshi.paperTrading.accounts.trades.list("acc_paper123")) {
    console.log(`${trade.type} ${trade.symbol}: ${trade.quantity} @ $${trade.price}`);
  }
  ```

  ```python Python theme={null}
  # Current holdings
  holdings = yoshi.paper_trading.accounts.holdings.list("acc_paper123")

  for h in holdings.holdings:
      print(f"{h.symbol}: {h.quantity} shares @ ${h.institution_price}")

  # Trade history
  for trade in yoshi.paper_trading.accounts.trades.list("acc_paper123"):
      print(f"{trade.type} {trade.symbol}: {trade.quantity} @ ${trade.price}")
  ```
</CodeGroup>

## What's next

<CardGroup cols={2}>
  <Card title="Actions & Approvals" icon="check-double" href="/guides/actions-approvals">
    Understand the full approval lifecycle.
  </Card>

  <Card title="Idempotency" icon="fingerprint" href="/concepts/idempotency">
    Prevent duplicate operations.
  </Card>
</CardGroup>
