Skip to content

Commit a82a1d7

Browse files
TexasCodingclaude
andcommitted
Add comprehensive Trade Data API support
Implements Phase 1.2 of the v3.0.0 development plan with full trade-level market data functionality. Features: - Historical trades retrieval with time range filtering - Latest trade data for single and multiple symbols - Automatic pagination support with get_all_trades() - Multi-symbol batch operations - Data feed selection (IEX, SIP, OTC) - As-of parameter for historical point-in-time data - RFC-3339 date validation and error handling Models: - TradeModel: Individual trade data with exchange, price, size, conditions - TradesResponse: Paginated response with next_page_token support - Full type safety with proper validation API Coverage: - GET /v2/stocks/{symbol}/trades - Historical trades - GET /v2/stocks/trades/latest - Latest trades - GET /v2/stocks/trades - Multi-symbol trades Tests: - 12 comprehensive unit tests with mocking - 10 integration tests for live API validation - Error handling and edge case coverage - Pagination and feed parameter validation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 299903e commit a82a1d7

File tree

7 files changed

+1173
-18
lines changed

7 files changed

+1173
-18
lines changed

DEVELOPMENT_PLAN.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,22 @@ main
7070
- All models have proper type hints
7171
- 100% test coverage
7272

73-
#### 1.2 Trade Data Support
73+
#### 1.2 Trade Data Support
7474
**Branch**: `feature/trade-data-api`
7575
**Priority**: 🔴 Critical
7676
**Estimated Time**: 2 days
77+
**Actual Time**: < 1 day
78+
**Completed**: 2025-01-14
7779

7880
**Tasks**:
79-
- [ ] Create `stock/trades.py` module
80-
- [ ] Implement `get_trades()` method with pagination
81-
- [ ] Implement `get_latest_trade()` method
82-
- [ ] Implement `get_trades_multi()` for multiple symbols
83-
- [ ] Create `TradeModel` dataclass
84-
- [ ] Add feed parameter support (iex, sip, otc)
85-
- [ ] Add comprehensive tests (10+ test cases)
86-
- [ ] Update documentation
81+
- [x] Create `stock/trades.py` module
82+
- [x] Implement `get_trades()` method with pagination
83+
- [x] Implement `get_latest_trade()` method
84+
- [x] Implement `get_trades_multi()` for multiple symbols
85+
- [x] Create `TradeModel` dataclass
86+
- [x] Add feed parameter support (iex, sip, otc)
87+
- [x] Add comprehensive tests (12 unit tests, 10 integration tests)
88+
- [x] Update documentation
8789

8890
**Acceptance Criteria**:
8991
- Can retrieve historical trades with proper pagination
@@ -283,11 +285,11 @@ main
283285

284286
## 📈 Progress Tracking
285287

286-
### Overall Progress: 🟦 10% Complete
288+
### Overall Progress: 🟦 20% Complete
287289

288290
| Phase | Status | Progress | Estimated Completion |
289291
|-------|--------|----------|---------------------|
290-
| Phase 1: Critical Features | 🟦 In Progress | 33% | Week 3 |
292+
| Phase 1: Critical Features | 🟦 In Progress | 67% | Week 3 |
291293
| Phase 2: Important Enhancements | ⬜ Not Started | 0% | Week 5 |
292294
| Phase 3: Performance & Quality | ⬜ Not Started | 0% | Week 7 |
293295
| Phase 4: Advanced Features | ⬜ Not Started | 0% | Week 10 |

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,52 @@ all_actions = api.trading.corporate_actions.get_announcements(
245245
)
246246
```
247247

248+
### Trade Data
249+
250+
```python
251+
# Get historical trades for a symbol
252+
trades_response = api.stock.trades.get_trades(
253+
symbol="AAPL",
254+
start="2024-01-15T09:30:00Z",
255+
end="2024-01-15T10:00:00Z",
256+
limit=100
257+
)
258+
259+
for trade in trades_response.trades:
260+
print(f"Trade: {trade.size} shares @ ${trade.price} on {trade.exchange}")
261+
262+
# Get latest trade for a symbol
263+
latest_trade = api.stock.trades.get_latest_trade("MSFT")
264+
print(f"Latest MSFT trade: ${latest_trade.price} x {latest_trade.size}")
265+
266+
# Get trades for multiple symbols
267+
multi_trades = api.stock.trades.get_trades_multi(
268+
symbols=["AAPL", "MSFT", "GOOGL"],
269+
start="2024-01-15T09:30:00Z",
270+
end="2024-01-15T10:00:00Z",
271+
limit=10
272+
)
273+
274+
for symbol, trades_data in multi_trades.items():
275+
print(f"{symbol}: {len(trades_data.trades)} trades")
276+
277+
# Get all trades with automatic pagination
278+
all_trades = api.stock.trades.get_all_trades(
279+
symbol="SPY",
280+
start="2024-01-15T09:30:00Z",
281+
end="2024-01-15T09:35:00Z"
282+
)
283+
print(f"Total SPY trades: {len(all_trades)}")
284+
285+
# Use different data feeds (requires subscription)
286+
sip_trades = api.stock.trades.get_trades(
287+
symbol="AAPL",
288+
start="2024-01-15T09:30:00Z",
289+
end="2024-01-15T10:00:00Z",
290+
feed="sip" # or "iex", "otc"
291+
)
292+
```
293+
248294
### Advanced Order Types
249295

250296
```python
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from dataclasses import dataclass
2+
from typing import Any
3+
4+
5+
@dataclass
6+
class TradeModel:
7+
"""Model for individual stock trade data."""
8+
9+
timestamp: str # RFC-3339 format timestamp
10+
symbol: str
11+
exchange: str
12+
price: float
13+
size: int
14+
conditions: list[str] | None
15+
id: int
16+
tape: str
17+
18+
19+
def trade_class_from_dict(
20+
data: dict[str, Any], symbol: str | None = None
21+
) -> TradeModel:
22+
"""Create TradeModel from API response dictionary.
23+
24+
Args:
25+
data: Dictionary containing trade data from API
26+
symbol: Optional symbol to use if not in data
27+
28+
Returns:
29+
TradeModel instance
30+
"""
31+
return TradeModel(
32+
timestamp=data.get("t", ""),
33+
symbol=data.get("symbol", symbol or ""),
34+
exchange=data.get("x", ""),
35+
price=float(data.get("p", 0.0)),
36+
size=int(data.get("s", 0)),
37+
conditions=data.get("c", []),
38+
id=int(data.get("i", 0)),
39+
tape=data.get("z", ""),
40+
)
41+
42+
43+
@dataclass
44+
class LatestTradeModel:
45+
"""Model for latest trade data with symbol."""
46+
47+
trade: TradeModel
48+
symbol: str
49+
50+
51+
@dataclass
52+
class TradesResponse:
53+
"""Response model for trades endpoint with pagination."""
54+
55+
trades: list[TradeModel]
56+
symbol: str
57+
next_page_token: str | None = None
58+
59+
60+
def extract_trades_data(data: dict[str, Any]) -> dict[str, Any]:
61+
"""Extract and transform trades data from API response.
62+
63+
Args:
64+
data: Raw API response data
65+
66+
Returns:
67+
Transformed dictionary ready for model creation
68+
"""
69+
# Handle both single trade and multiple trades response formats
70+
if "trades" in data:
71+
# Multiple trades response
72+
return data
73+
if "trade" in data:
74+
# Single latest trade response
75+
return {"trades": [data["trade"]], "symbol": data.get("symbol", "")}
76+
# Direct trade data
77+
return {"trades": [data], "symbol": data.get("symbol", "")}

src/py_alpaca_api/stock/__init__.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from py_alpaca_api.stock.latest_quote import LatestQuote
44
from py_alpaca_api.stock.predictor import Predictor
55
from py_alpaca_api.stock.screener import Screener
6+
from py_alpaca_api.stock.trades import Trades
67
from py_alpaca_api.trading.market import Market
78

89

@@ -25,13 +26,6 @@ def __init__(
2526
headers=headers, base_url=base_url, data_url=data_url, market=market
2627
)
2728

28-
self._initialize_components(
29-
headers=headers,
30-
base_url=base_url,
31-
data_url=data_url,
32-
market=market,
33-
)
34-
3529
def _initialize_components(
3630
self,
3731
headers: dict[str, str],
@@ -46,3 +40,4 @@ def _initialize_components(
4640
)
4741
self.predictor = Predictor(history=self.history, screener=self.screener)
4842
self.latest_quote = LatestQuote(headers=headers)
43+
self.trades = Trades(headers=headers)

0 commit comments

Comments
 (0)