robin-sdk 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
robin_sdk/__init__.py ADDED
@@ -0,0 +1,37 @@
1
+ """
2
+ Robin SDK — Python SDK for Robinhood MCP Trading API.
3
+
4
+ Zero third-party runtime dependencies. Uses only the Python standard library.
5
+
6
+ Usage:
7
+ >>> from robin_sdk import RobinClient
8
+ >>> async with RobinClient(client_id="your_id") as client:
9
+ ... accounts = await client.get_accounts()
10
+ """
11
+
12
+ __version__ = "0.1.0"
13
+
14
+ from robin_sdk.client import RobinClient
15
+ from robin_sdk.exceptions import (
16
+ RobinSDKError,
17
+ AuthenticationError,
18
+ TokenExpiredError,
19
+ TransportError,
20
+ APIError,
21
+ OrderError,
22
+ AccountError,
23
+ ValidationError,
24
+ )
25
+
26
+ __all__ = [
27
+ "RobinClient",
28
+ "RobinSDKError",
29
+ "AuthenticationError",
30
+ "TokenExpiredError",
31
+ "TransportError",
32
+ "APIError",
33
+ "OrderError",
34
+ "AccountError",
35
+ "ValidationError",
36
+ "__version__",
37
+ ]
robin_sdk/_compat.py ADDED
@@ -0,0 +1,31 @@
1
+ """
2
+ Python version compatibility shims.
3
+
4
+ Keeps the rest of the codebase clean by centralising version checks here.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import sys
10
+
11
+ PYTHON_39 = sys.version_info >= (3, 9)
12
+ PYTHON_310 = sys.version_info >= (3, 10)
13
+ PYTHON_311 = sys.version_info >= (3, 11)
14
+
15
+
16
+ def removeprefix(s: str, prefix: str) -> str:
17
+ """str.removeprefix backport for Python < 3.9."""
18
+ if PYTHON_39:
19
+ return s.removeprefix(prefix) # type: ignore[attr-defined]
20
+ if s.startswith(prefix):
21
+ return s[len(prefix):]
22
+ return s
23
+
24
+
25
+ def removesuffix(s: str, suffix: str) -> str:
26
+ """str.removesuffix backport for Python < 3.9."""
27
+ if PYTHON_39:
28
+ return s.removesuffix(suffix) # type: ignore[attr-defined]
29
+ if suffix and s.endswith(suffix):
30
+ return s[:-len(suffix)]
31
+ return s
robin_sdk/_types.py ADDED
@@ -0,0 +1,231 @@
1
+ """
2
+ Type definitions for Robin SDK.
3
+
4
+ Uses TypedDict for structured response data so callers get editor
5
+ autocompletion without requiring runtime dependencies.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import sys
11
+ from typing import Any, Dict, List, Optional
12
+
13
+ if sys.version_info >= (3, 12):
14
+ from typing import TypedDict, NotRequired
15
+ elif sys.version_info >= (3, 11):
16
+ from typing import TypedDict, NotRequired
17
+ else:
18
+ from typing import TypedDict
19
+
20
+ # Python 3.9-3.10 backport for NotRequired
21
+ class _NotRequiredMeta(type):
22
+ def __getitem__(cls, item):
23
+ return item
24
+
25
+ class NotRequired(metaclass=_NotRequiredMeta): # type: ignore[no-redef]
26
+ pass
27
+
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # OAuth / Auth types
31
+ # ---------------------------------------------------------------------------
32
+
33
+ class TokenData(TypedDict):
34
+ """Cached token data stored on disk."""
35
+ access_token: str
36
+ refresh_token: Optional[str]
37
+ timestamp: str
38
+ expires_in: int
39
+
40
+
41
+ class OAuthEndpoints(TypedDict):
42
+ """Discovered OAuth2 endpoint URLs."""
43
+ auth_url: str
44
+ token_url: str
45
+ scopes: List[str]
46
+
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # Account & Portfolio types
50
+ # ---------------------------------------------------------------------------
51
+
52
+ class Account(TypedDict, total=False):
53
+ """A Robinhood brokerage account."""
54
+ account_number: str
55
+ id: str
56
+ brokerage_account_type: str
57
+ type: str
58
+ nickname: str
59
+ is_default: bool
60
+ agentic_allowed: bool
61
+
62
+
63
+ class PortfolioData(TypedDict, total=False):
64
+ """Portfolio snapshot values."""
65
+ portfolio_value: float
66
+ cash_value: float
67
+ buying_power: float
68
+ equity_value: float
69
+ market_value: float
70
+ total_value: float
71
+ total_equity: float
72
+ extended_hours_equity: float
73
+ dividend_total: float
74
+ total_return: float
75
+
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # Equity types
79
+ # ---------------------------------------------------------------------------
80
+
81
+ class EquityPosition(TypedDict, total=False):
82
+ """An open equity position."""
83
+ symbol: str
84
+ ticker: str
85
+ quantity: float
86
+ average_buy_price: float
87
+ value: float
88
+
89
+
90
+ class EquityQuote(TypedDict, total=False):
91
+ """Real-time equity quote."""
92
+ symbol: str
93
+ last_trade_price: float
94
+ previous_close: float
95
+ bid_price: float
96
+ ask_price: float
97
+
98
+
99
+ class EquityOrder(TypedDict, total=False):
100
+ """An equity order record."""
101
+ order_id: str
102
+ id: str
103
+ state: str
104
+ status: str
105
+ side: str
106
+ symbol: str
107
+ quantity: str
108
+ price: str
109
+ average_fill_price: str
110
+ created_at: str
111
+ updated_at: str
112
+
113
+
114
+ class TradabilityInfo(TypedDict, total=False):
115
+ """Whether a symbol can be traded."""
116
+ symbol: str
117
+ tradable: bool
118
+ fractional: bool
119
+
120
+
121
+ # ---------------------------------------------------------------------------
122
+ # Option types
123
+ # ---------------------------------------------------------------------------
124
+
125
+ class OptionChain(TypedDict, total=False):
126
+ """Option chain data for a symbol."""
127
+ symbol: str
128
+ expiration_dates: List[str]
129
+ chain_id: str
130
+
131
+
132
+ class OptionInstrument(TypedDict, total=False):
133
+ """An individual option contract."""
134
+ instrument_id: str
135
+ symbol: str
136
+ expiration_date: str
137
+ strike_price: float
138
+ option_type: str
139
+
140
+
141
+ class OptionQuote(TypedDict, total=False):
142
+ """Real-time option quote."""
143
+ instrument_id: str
144
+ mark_price: float
145
+ bid_price: float
146
+ ask_price: float
147
+
148
+
149
+ class OptionPosition(TypedDict, total=False):
150
+ """An open or closed option position."""
151
+ instrument_id: str
152
+ symbol: str
153
+ quantity: float
154
+ average_price: float
155
+
156
+
157
+ class OptionOrder(TypedDict, total=False):
158
+ """An option order record."""
159
+ order_id: str
160
+ id: str
161
+ state: str
162
+ side: str
163
+ quantity: str
164
+ price: str
165
+ created_at: str
166
+
167
+
168
+ # ---------------------------------------------------------------------------
169
+ # Watchlist types
170
+ # ---------------------------------------------------------------------------
171
+
172
+ class Watchlist(TypedDict, total=False):
173
+ """A user watchlist."""
174
+ watchlist_id: str
175
+ id: str
176
+ name: str
177
+ item_count: int
178
+
179
+
180
+ class WatchlistItem(TypedDict, total=False):
181
+ """An item in a watchlist."""
182
+ symbol: str
183
+ instrument_id: str
184
+
185
+
186
+ # ---------------------------------------------------------------------------
187
+ # Market Data types
188
+ # ---------------------------------------------------------------------------
189
+
190
+ class HistoricalBar(TypedDict, total=False):
191
+ """An OHLCV price bar."""
192
+ begins_at: str
193
+ open_price: float
194
+ close_price: float
195
+ high_price: float
196
+ low_price: float
197
+ volume: int
198
+
199
+
200
+ class IndexData(TypedDict, total=False):
201
+ """Market index information."""
202
+ symbol: str
203
+ name: str
204
+ value: float
205
+
206
+
207
+ # ---------------------------------------------------------------------------
208
+ # JSON-RPC types (internal)
209
+ # ---------------------------------------------------------------------------
210
+
211
+ class JSONRPCRequest(TypedDict):
212
+ """A JSON-RPC 2.0 request."""
213
+ jsonrpc: str
214
+ id: int
215
+ method: str
216
+ params: Dict[str, Any]
217
+
218
+
219
+ class JSONRPCError(TypedDict, total=False):
220
+ """A JSON-RPC 2.0 error object."""
221
+ code: int
222
+ message: str
223
+ data: Any
224
+
225
+
226
+ class JSONRPCResponse(TypedDict, total=False):
227
+ """A JSON-RPC 2.0 response."""
228
+ jsonrpc: str
229
+ id: int
230
+ result: Any
231
+ error: JSONRPCError