Environment
Language
Python 3.12.3
Alpaca SDK Version
alpaca-trade-api v3.2.0
Other Environment Details
Detail | Value
OS | Ubuntu 24.04.4 LTS (Noble Numbat)
Kernel | Linux 6.8.0-134-generic
Host | srv1621471 (Hostinger KVM2 VPS)
API Base | https://paper-api.alpaca.markets
SDK Location | /usr/local/lib/python3.12/dist-packages
SDK Dependencies | aiohttp, deprecation, msgpack, numpy, pandas, PyYAML, requests, urllib3, websocket-client, websocke
Problem
Summary
On July 6: Paper account held 26 positions, ~$115K equity.
On July 7 at market open (~13:30 UTC): Positions API returned only 3 positions (ARM, DOCU, V — all shorts). 23 positions vanished with no sell orders, no liquidation records, no account activity.
The last_equity field shows $115,276.04 vs current equity $24,726.65 — the account “remembers” the higher balance.
Paper or Live Trading?
Paper - PA3VTK6DNR6E
Example Code
Reproduction Script
'#!/usr/bin/env python3
“”"
Reproduces the Alpaca paper account position disappearance.
Run this after market open to verify positions API vs expected holdings.
“”"
from alpaca_trade_api import REST
import os
— CONFIG —
API_KEY = “YOUR_KEY”
API_SECRET = “YOUR_SECRET”
BASE_URL = “https://paper-api.alpaca.markets” # Paper trading
— REPRO —
api = REST(API_KEY, API_SECRET, BASE_URL)
account = api.get_account()
positions = api.list_positions()
print(f"Account Equity: ${float(account.equity):,.2f}“)
print(f"Last Equity: ${float(account.last_equity):,.2f}”)
print(f"Divergence: ${float(account.last_equity) - float(account.equity):,.2f}“)
print(f"Positions count: {len(positions)}”)
print()
for p in positions:
print(f" {p.symbol}: qty={p.qty}, avg_entry=${p.avg_entry_price}, mkt_val=${p.market_value}")’
Expected vs Actual
Expected (July 6 close): 26 positions, ~$115K equity
Actual (July 7 13:30 UTC): 3 positions, ~$24K equity
The Bug in Our Code
The issue is in clawtrader.py:3534-3537 — we blindly overwrite local state with Alpaca’s positions:
state_data = self.state.load()
state_data[“positions”] = {sym: {“qty”: pos.qty, …} for sym, pos in positions.items()}
self.state.save(state_data) # ← wipes 23 positions without validation
No validation: We don’t check if position count dropped >50%, or if equity diverged >20%. We just trust the API and overwrite.
