fivetwenty 0.1.0__tar.gz

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.
Files changed (39) hide show
  1. fivetwenty-0.1.0/LICENSE +21 -0
  2. fivetwenty-0.1.0/PKG-INFO +309 -0
  3. fivetwenty-0.1.0/README.md +281 -0
  4. fivetwenty-0.1.0/fivetwenty/__init__.py +62 -0
  5. fivetwenty-0.1.0/fivetwenty/_internal/__init__.py +1 -0
  6. fivetwenty-0.1.0/fivetwenty/_internal/environment.py +17 -0
  7. fivetwenty-0.1.0/fivetwenty/_internal/utils.py +113 -0
  8. fivetwenty-0.1.0/fivetwenty/client.py +567 -0
  9. fivetwenty-0.1.0/fivetwenty/configuration.py +215 -0
  10. fivetwenty-0.1.0/fivetwenty/endpoints/__init__.py +1 -0
  11. fivetwenty-0.1.0/fivetwenty/endpoints/accounts.py +183 -0
  12. fivetwenty-0.1.0/fivetwenty/endpoints/instruments.py +106 -0
  13. fivetwenty-0.1.0/fivetwenty/endpoints/orders.py +656 -0
  14. fivetwenty-0.1.0/fivetwenty/endpoints/positions.py +164 -0
  15. fivetwenty-0.1.0/fivetwenty/endpoints/pricing.py +360 -0
  16. fivetwenty-0.1.0/fivetwenty/endpoints/trades.py +248 -0
  17. fivetwenty-0.1.0/fivetwenty/endpoints/transactions.py +271 -0
  18. fivetwenty-0.1.0/fivetwenty/exceptions.py +198 -0
  19. fivetwenty-0.1.0/fivetwenty/models/__init__.py +210 -0
  20. fivetwenty-0.1.0/fivetwenty/models/accounts.py +263 -0
  21. fivetwenty-0.1.0/fivetwenty/models/base.py +58 -0
  22. fivetwenty-0.1.0/fivetwenty/models/enums.py +494 -0
  23. fivetwenty-0.1.0/fivetwenty/models/error_codes.py +225 -0
  24. fivetwenty-0.1.0/fivetwenty/models/error_details.py +290 -0
  25. fivetwenty-0.1.0/fivetwenty/models/instruments.py +100 -0
  26. fivetwenty-0.1.0/fivetwenty/models/orders.py +620 -0
  27. fivetwenty-0.1.0/fivetwenty/models/positions.py +69 -0
  28. fivetwenty-0.1.0/fivetwenty/models/pricing.py +140 -0
  29. fivetwenty-0.1.0/fivetwenty/models/streaming.py +42 -0
  30. fivetwenty-0.1.0/fivetwenty/models/trades.py +99 -0
  31. fivetwenty-0.1.0/fivetwenty/models/transactions.py +540 -0
  32. fivetwenty-0.1.0/fivetwenty/py.typed +1 -0
  33. fivetwenty-0.1.0/fivetwenty.egg-info/PKG-INFO +309 -0
  34. fivetwenty-0.1.0/fivetwenty.egg-info/SOURCES.txt +37 -0
  35. fivetwenty-0.1.0/fivetwenty.egg-info/dependency_links.txt +1 -0
  36. fivetwenty-0.1.0/fivetwenty.egg-info/requires.txt +2 -0
  37. fivetwenty-0.1.0/fivetwenty.egg-info/top_level.txt +1 -0
  38. fivetwenty-0.1.0/pyproject.toml +291 -0
  39. fivetwenty-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 FiveTwenty Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,309 @@
1
+ Metadata-Version: 2.4
2
+ Name: fivetwenty
3
+ Version: 0.1.0
4
+ Summary: Simple, elegant Python client for OANDA's REST API v20
5
+ Author: FiveTwenty Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/NimbleOx/fivetwenty
8
+ Project-URL: Repository, https://github.com/NimbleOx/fivetwenty
9
+ Project-URL: Documentation, https://github.com/NimbleOx/fivetwenty
10
+ Project-URL: Bug Reports, https://github.com/NimbleOx/fivetwenty/issues
11
+ Keywords: oanda,trading,forex,api,finance
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Financial and Insurance Industry
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Office/Business :: Financial :: Investment
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: httpx>=0.25.0
26
+ Requires-Dist: pydantic>=2.5.0
27
+ Dynamic: license-file
28
+
29
+ # FiveTwenty
30
+
31
+ A comprehensive, production-ready Python client for the OANDA REST v20.
32
+
33
+ ## Features
34
+
35
+ - **Async-first** with sync wrapper
36
+ - **Type-safe** with full mypy strict compliance and 75+ comprehensive models
37
+ - **Minimal dependencies** (only httpx + pydantic)
38
+ - **Production ready** with retries, rate limiting, and comprehensive error handling
39
+ - **Reliable streaming** with configurable reconnection policies and heartbeat monitoring
40
+ - **Financial precision** with Decimal calculations and proper OANDA field aliases
41
+ - **Complete API coverage** with 100% endpoint implementation (all 7 endpoint groups)
42
+ - **Extensive testing** with 427 comprehensive tests and roundtrip validation
43
+
44
+ ## Quick Start
45
+
46
+ ### Installation
47
+
48
+ ```bash
49
+ # Note: Package not yet published to PyPI - install from source
50
+ git clone https://github.com/NimbleOx/fivetwenty.git
51
+ cd fivetwenty
52
+ uv pip install -e .
53
+ ```
54
+
55
+ ### Async Usage (Recommended)
56
+
57
+ ```python
58
+ import asyncio
59
+ from decimal import Decimal
60
+ from fivetwenty import AsyncClient, Environment
61
+
62
+ async def main():
63
+ async with AsyncClient(
64
+ token="your-token-here",
65
+ environment=Environment.PRACTICE
66
+ ) as client:
67
+
68
+ # Get accounts
69
+ accounts = await client.accounts.list()
70
+ account_id = accounts[0].id
71
+
72
+ # Create a market order
73
+ order = await client.orders.post_market_order(
74
+ account_id=account_id,
75
+ instrument="EUR_USD",
76
+ units=1000,
77
+ stop_loss=Decimal("1.0900"),
78
+ take_profit=Decimal("1.1100"),
79
+ )
80
+ print(f"Order created: {order.last_transaction_id}")
81
+
82
+ # Stream prices for 30 seconds
83
+ import time
84
+ end_time = time.time() + 30
85
+
86
+ async for price in client.pricing.stream(account_id, ["EUR_USD"]):
87
+ if hasattr(price, 'instrument'): # It's a price update
88
+ spread = price.spread
89
+ print(f"{price.instrument}: {price.closeout_bid}/{price.closeout_ask} (spread: {spread})")
90
+
91
+ if time.time() > end_time:
92
+ break
93
+
94
+ if __name__ == "__main__":
95
+ asyncio.run(main())
96
+ ```
97
+
98
+ ### Sync Usage
99
+
100
+ ```python
101
+ from decimal import Decimal
102
+ from fivetwenty import Client, Environment
103
+
104
+ with Client(token="your-token-here", environment=Environment.PRACTICE) as client:
105
+ # Get accounts
106
+ accounts = client.accounts.list()
107
+ account_id = accounts[0].id
108
+
109
+ # Create a market order
110
+ order = client.orders.post_market_order(
111
+ account_id=account_id,
112
+ instrument="EUR_USD",
113
+ units=1000,
114
+ stop_loss=Decimal("1.0900")
115
+ )
116
+
117
+ # Stream prices (blocking iterator)
118
+ count = 0
119
+ for price in client.pricing.stream_iter(account_id, ["EUR_USD"]):
120
+ if hasattr(price, 'instrument'):
121
+ print(f"{price.instrument}: {price.closeout_bid}/{price.closeout_ask}")
122
+
123
+ count += 1
124
+ if count > 10:
125
+ break # Stop after 10 updates
126
+ ```
127
+
128
+ ## Configuration
129
+
130
+ ### Environment Variables
131
+
132
+ - `FIVETWENTY_OANDA_TOKEN`: Your API token
133
+ - `FIVETWENTY_USER_AGENT_EXTRA`: Additional user agent info
134
+
135
+ ### Advanced Configuration
136
+
137
+ ```python
138
+ from fivetwenty import AsyncClient, Environment
139
+ import httpx
140
+
141
+ client = AsyncClient(
142
+ token="your-token",
143
+ environment=Environment.LIVE, # Use live trading
144
+ timeout=60.0, # 60 second timeout
145
+ max_retries=5, # Retry failed requests
146
+
147
+ # Custom HTTP client with proxy
148
+ transport=httpx.AsyncClient(
149
+ proxies="http://proxy.example.com:8080",
150
+ verify="/path/to/ca-bundle.crt"
151
+ ),
152
+
153
+ # Custom logging
154
+ logger=your_logger,
155
+ )
156
+ ```
157
+
158
+ ## Error Handling
159
+
160
+ ```python
161
+ from fivetwenty import VeeTwentyError, StreamStall
162
+
163
+ try:
164
+ order = await client.orders.post_market_order(...)
165
+ except VeeTwentyError as e:
166
+ print(f"API Error: {e}")
167
+ print(f"Status: {e.status}")
168
+ print(f"Code: {e.code}")
169
+ print(f"Request ID: {e.request_id}")
170
+
171
+ if e.retryable:
172
+ # Can retry this operation
173
+ pass
174
+
175
+ try:
176
+ async for price in client.pricing.stream(...):
177
+ process(price)
178
+ except StreamStall:
179
+ # Reconnect and try again
180
+ pass
181
+ ```
182
+
183
+ ## Architecture Highlights
184
+
185
+ ### Production-Ready Features
186
+ - **Smart retries** with exponential backoff and jitter
187
+ - **Rate limiting respect** honoring server `Retry-After` headers
188
+ - **Write-safe retries** - only retry POST/PUT/PATCH/DELETE with idempotency keys
189
+ - **Stall detection** using monotonic time for reliable stream monitoring
190
+ - **Token hygiene** - never logs sensitive authentication data
191
+
192
+ ### Financial Precision
193
+ - **Decimal precision** for all monetary calculations (never float)
194
+ - **OANDA API compatibility** with proper camelCase field aliases
195
+ - **String serialization** of Decimals to prevent floating-point errors
196
+ - **Roundtrip validation** ensuring data integrity with OANDA's API format
197
+
198
+ ### Developer Experience
199
+ - **Type safety** with full mypy strict compliance and `py.typed` marker
200
+ - **Comprehensive models** - 75+ Pydantic models covering the entire OANDA API
201
+ - **Intuitive API** - everything hangs off `client.accounts`, `client.orders`, `client.pricing`
202
+ - **Context managers** for automatic resource cleanup
203
+ - **Rich error messages** with request IDs and actionable information
204
+ - **VS Code ready** with included development environment configuration
205
+
206
+ ## Project Structure
207
+
208
+ ```
209
+ fivetwenty/
210
+ โ”œโ”€โ”€ __init__.py # Clean public API
211
+ โ”œโ”€โ”€ client.py # AsyncClient & Client implementations
212
+ โ”œโ”€โ”€ exceptions.py # Error handling with VeeTwentyError
213
+ โ”œโ”€โ”€ models.py # 75+ comprehensive OANDA API models
214
+ โ”œโ”€โ”€ endpoints/ # Complete endpoint implementations
215
+ โ”‚ โ”œโ”€โ”€ accounts.py # Account operations & configuration
216
+ โ”‚ โ”œโ”€โ”€ orders.py # Complete order management
217
+ โ”‚ โ”œโ”€โ”€ pricing.py # Pricing, streaming & candles
218
+ โ”‚ โ”œโ”€โ”€ trades.py # Trade management
219
+ โ”‚ โ”œโ”€โ”€ positions.py # Position operations
220
+ โ”‚ โ””โ”€โ”€ transactions.py # Transaction history & streaming
221
+ โ””โ”€โ”€ _internal/ # Internal utilities
222
+ โ”œโ”€โ”€ environment.py # Environment enum
223
+ โ””โ”€โ”€ utils.py # Helper functions
224
+ ```
225
+
226
+ ## Requirements
227
+
228
+ - Python 3.10+
229
+ - httpx >= 0.25.0
230
+ - pydantic >= 2.5.0
231
+
232
+ ## API Coverage
233
+
234
+ ### โœ… Complete OANDA v20 REST API Implementation (100%)
235
+
236
+ - **Account Management**: Complete account operations, configuration updates, and change polling
237
+ - **Order Operations**: Full order lifecycle - create, list, get, cancel, replace, and client extensions
238
+ - **Trade Management**: Complete trade operations - list, get, close, modify, and dependent orders
239
+ - **Position Management**: Full position operations - list, get, close by instrument
240
+ - **Pricing & Streaming**: Real-time pricing, reliable streaming, and historical candles
241
+ - **Transaction History**: Complete audit trail, streaming, and incremental updates
242
+
243
+ **All 7 endpoint groups implemented with 268 comprehensive tests!**
244
+
245
+ ## Development
246
+
247
+ This project uses **uv** for dependency management, **poethepoet** for task running, and **ruff** for formatting/linting:
248
+
249
+ ```bash
250
+ # Quick setup (poethepoet)
251
+ poe setup # Complete project setup for new developers
252
+ poe dev # Fast development checks (format, typecheck, test)
253
+ poe check # Run format, lint, typecheck, and tests
254
+
255
+ # Testing
256
+ poe test # Run all tests
257
+ poe test-cov # Run tests with coverage
258
+
259
+ # Code quality
260
+ poe quality-core # Run format, lint, and typecheck (core files only)
261
+ poe format # Format code
262
+ poe lint-fix # Fix linting issues
263
+
264
+ # Documentation
265
+ poe docs-serve # Serve docs locally
266
+ poe docs-build # Build documentation
267
+
268
+ # Or use uv directly
269
+ uv sync # Install dependencies
270
+ uv run pytest # Run tests
271
+ uv run ruff format . # Format code
272
+ uv run mypy fivetwenty/ # Type checking
273
+ ```
274
+
275
+ See [CLAUDE.md](CLAUDE.md) for detailed development guidance and [TODO.md](TODO.md) for planned features.
276
+
277
+ ## ๐Ÿ“š Documentation
278
+
279
+ This project features comprehensive documentation organized using the **Diรกtaxis framework** - a systematic approach that organizes content by user needs.
280
+
281
+ ### Documentation Structure
282
+
283
+ | | **PRACTICAL USE** | **THEORETICAL KNOWLEDGE** |
284
+ |-------------------|-----------------------------------|---------------------------------|
285
+ | **LEARNING-ORIENTED** | ๐Ÿ“š **TUTORIALS**<br>(Learning by doing) | ๐Ÿ“– **EXPLANATION**<br>(Understanding) |
286
+ | **PROBLEM-ORIENTED** | ๐Ÿ› ๏ธ **HOW-TO GUIDES**<br>(Solving problems) | ๐Ÿ“‹ **REFERENCE**<br>(Information lookup) |
287
+
288
+ ### Working with Documentation
289
+
290
+ ```bash
291
+ # Install documentation dependencies
292
+ uv pip install -e .[docs]
293
+
294
+ # Serve documentation locally (available at http://localhost:8000)
295
+ uv run mkdocs serve
296
+
297
+ # Build documentation for production
298
+ uv run mkdocs build
299
+
300
+ # Or use poe tasks
301
+ uv run poe docs-serve # Serve locally
302
+ uv run poe docs-build # Build for production
303
+ ```
304
+
305
+ The documentation includes tutorials, how-to guides, API reference, and conceptual explanations. Visit the documentation site for complete details.
306
+
307
+ ## License
308
+
309
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,281 @@
1
+ # FiveTwenty
2
+
3
+ A comprehensive, production-ready Python client for the OANDA REST v20.
4
+
5
+ ## Features
6
+
7
+ - **Async-first** with sync wrapper
8
+ - **Type-safe** with full mypy strict compliance and 75+ comprehensive models
9
+ - **Minimal dependencies** (only httpx + pydantic)
10
+ - **Production ready** with retries, rate limiting, and comprehensive error handling
11
+ - **Reliable streaming** with configurable reconnection policies and heartbeat monitoring
12
+ - **Financial precision** with Decimal calculations and proper OANDA field aliases
13
+ - **Complete API coverage** with 100% endpoint implementation (all 7 endpoint groups)
14
+ - **Extensive testing** with 427 comprehensive tests and roundtrip validation
15
+
16
+ ## Quick Start
17
+
18
+ ### Installation
19
+
20
+ ```bash
21
+ # Note: Package not yet published to PyPI - install from source
22
+ git clone https://github.com/NimbleOx/fivetwenty.git
23
+ cd fivetwenty
24
+ uv pip install -e .
25
+ ```
26
+
27
+ ### Async Usage (Recommended)
28
+
29
+ ```python
30
+ import asyncio
31
+ from decimal import Decimal
32
+ from fivetwenty import AsyncClient, Environment
33
+
34
+ async def main():
35
+ async with AsyncClient(
36
+ token="your-token-here",
37
+ environment=Environment.PRACTICE
38
+ ) as client:
39
+
40
+ # Get accounts
41
+ accounts = await client.accounts.list()
42
+ account_id = accounts[0].id
43
+
44
+ # Create a market order
45
+ order = await client.orders.post_market_order(
46
+ account_id=account_id,
47
+ instrument="EUR_USD",
48
+ units=1000,
49
+ stop_loss=Decimal("1.0900"),
50
+ take_profit=Decimal("1.1100"),
51
+ )
52
+ print(f"Order created: {order.last_transaction_id}")
53
+
54
+ # Stream prices for 30 seconds
55
+ import time
56
+ end_time = time.time() + 30
57
+
58
+ async for price in client.pricing.stream(account_id, ["EUR_USD"]):
59
+ if hasattr(price, 'instrument'): # It's a price update
60
+ spread = price.spread
61
+ print(f"{price.instrument}: {price.closeout_bid}/{price.closeout_ask} (spread: {spread})")
62
+
63
+ if time.time() > end_time:
64
+ break
65
+
66
+ if __name__ == "__main__":
67
+ asyncio.run(main())
68
+ ```
69
+
70
+ ### Sync Usage
71
+
72
+ ```python
73
+ from decimal import Decimal
74
+ from fivetwenty import Client, Environment
75
+
76
+ with Client(token="your-token-here", environment=Environment.PRACTICE) as client:
77
+ # Get accounts
78
+ accounts = client.accounts.list()
79
+ account_id = accounts[0].id
80
+
81
+ # Create a market order
82
+ order = client.orders.post_market_order(
83
+ account_id=account_id,
84
+ instrument="EUR_USD",
85
+ units=1000,
86
+ stop_loss=Decimal("1.0900")
87
+ )
88
+
89
+ # Stream prices (blocking iterator)
90
+ count = 0
91
+ for price in client.pricing.stream_iter(account_id, ["EUR_USD"]):
92
+ if hasattr(price, 'instrument'):
93
+ print(f"{price.instrument}: {price.closeout_bid}/{price.closeout_ask}")
94
+
95
+ count += 1
96
+ if count > 10:
97
+ break # Stop after 10 updates
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ ### Environment Variables
103
+
104
+ - `FIVETWENTY_OANDA_TOKEN`: Your API token
105
+ - `FIVETWENTY_USER_AGENT_EXTRA`: Additional user agent info
106
+
107
+ ### Advanced Configuration
108
+
109
+ ```python
110
+ from fivetwenty import AsyncClient, Environment
111
+ import httpx
112
+
113
+ client = AsyncClient(
114
+ token="your-token",
115
+ environment=Environment.LIVE, # Use live trading
116
+ timeout=60.0, # 60 second timeout
117
+ max_retries=5, # Retry failed requests
118
+
119
+ # Custom HTTP client with proxy
120
+ transport=httpx.AsyncClient(
121
+ proxies="http://proxy.example.com:8080",
122
+ verify="/path/to/ca-bundle.crt"
123
+ ),
124
+
125
+ # Custom logging
126
+ logger=your_logger,
127
+ )
128
+ ```
129
+
130
+ ## Error Handling
131
+
132
+ ```python
133
+ from fivetwenty import VeeTwentyError, StreamStall
134
+
135
+ try:
136
+ order = await client.orders.post_market_order(...)
137
+ except VeeTwentyError as e:
138
+ print(f"API Error: {e}")
139
+ print(f"Status: {e.status}")
140
+ print(f"Code: {e.code}")
141
+ print(f"Request ID: {e.request_id}")
142
+
143
+ if e.retryable:
144
+ # Can retry this operation
145
+ pass
146
+
147
+ try:
148
+ async for price in client.pricing.stream(...):
149
+ process(price)
150
+ except StreamStall:
151
+ # Reconnect and try again
152
+ pass
153
+ ```
154
+
155
+ ## Architecture Highlights
156
+
157
+ ### Production-Ready Features
158
+ - **Smart retries** with exponential backoff and jitter
159
+ - **Rate limiting respect** honoring server `Retry-After` headers
160
+ - **Write-safe retries** - only retry POST/PUT/PATCH/DELETE with idempotency keys
161
+ - **Stall detection** using monotonic time for reliable stream monitoring
162
+ - **Token hygiene** - never logs sensitive authentication data
163
+
164
+ ### Financial Precision
165
+ - **Decimal precision** for all monetary calculations (never float)
166
+ - **OANDA API compatibility** with proper camelCase field aliases
167
+ - **String serialization** of Decimals to prevent floating-point errors
168
+ - **Roundtrip validation** ensuring data integrity with OANDA's API format
169
+
170
+ ### Developer Experience
171
+ - **Type safety** with full mypy strict compliance and `py.typed` marker
172
+ - **Comprehensive models** - 75+ Pydantic models covering the entire OANDA API
173
+ - **Intuitive API** - everything hangs off `client.accounts`, `client.orders`, `client.pricing`
174
+ - **Context managers** for automatic resource cleanup
175
+ - **Rich error messages** with request IDs and actionable information
176
+ - **VS Code ready** with included development environment configuration
177
+
178
+ ## Project Structure
179
+
180
+ ```
181
+ fivetwenty/
182
+ โ”œโ”€โ”€ __init__.py # Clean public API
183
+ โ”œโ”€โ”€ client.py # AsyncClient & Client implementations
184
+ โ”œโ”€โ”€ exceptions.py # Error handling with VeeTwentyError
185
+ โ”œโ”€โ”€ models.py # 75+ comprehensive OANDA API models
186
+ โ”œโ”€โ”€ endpoints/ # Complete endpoint implementations
187
+ โ”‚ โ”œโ”€โ”€ accounts.py # Account operations & configuration
188
+ โ”‚ โ”œโ”€โ”€ orders.py # Complete order management
189
+ โ”‚ โ”œโ”€โ”€ pricing.py # Pricing, streaming & candles
190
+ โ”‚ โ”œโ”€โ”€ trades.py # Trade management
191
+ โ”‚ โ”œโ”€โ”€ positions.py # Position operations
192
+ โ”‚ โ””โ”€โ”€ transactions.py # Transaction history & streaming
193
+ โ””โ”€โ”€ _internal/ # Internal utilities
194
+ โ”œโ”€โ”€ environment.py # Environment enum
195
+ โ””โ”€โ”€ utils.py # Helper functions
196
+ ```
197
+
198
+ ## Requirements
199
+
200
+ - Python 3.10+
201
+ - httpx >= 0.25.0
202
+ - pydantic >= 2.5.0
203
+
204
+ ## API Coverage
205
+
206
+ ### โœ… Complete OANDA v20 REST API Implementation (100%)
207
+
208
+ - **Account Management**: Complete account operations, configuration updates, and change polling
209
+ - **Order Operations**: Full order lifecycle - create, list, get, cancel, replace, and client extensions
210
+ - **Trade Management**: Complete trade operations - list, get, close, modify, and dependent orders
211
+ - **Position Management**: Full position operations - list, get, close by instrument
212
+ - **Pricing & Streaming**: Real-time pricing, reliable streaming, and historical candles
213
+ - **Transaction History**: Complete audit trail, streaming, and incremental updates
214
+
215
+ **All 7 endpoint groups implemented with 268 comprehensive tests!**
216
+
217
+ ## Development
218
+
219
+ This project uses **uv** for dependency management, **poethepoet** for task running, and **ruff** for formatting/linting:
220
+
221
+ ```bash
222
+ # Quick setup (poethepoet)
223
+ poe setup # Complete project setup for new developers
224
+ poe dev # Fast development checks (format, typecheck, test)
225
+ poe check # Run format, lint, typecheck, and tests
226
+
227
+ # Testing
228
+ poe test # Run all tests
229
+ poe test-cov # Run tests with coverage
230
+
231
+ # Code quality
232
+ poe quality-core # Run format, lint, and typecheck (core files only)
233
+ poe format # Format code
234
+ poe lint-fix # Fix linting issues
235
+
236
+ # Documentation
237
+ poe docs-serve # Serve docs locally
238
+ poe docs-build # Build documentation
239
+
240
+ # Or use uv directly
241
+ uv sync # Install dependencies
242
+ uv run pytest # Run tests
243
+ uv run ruff format . # Format code
244
+ uv run mypy fivetwenty/ # Type checking
245
+ ```
246
+
247
+ See [CLAUDE.md](CLAUDE.md) for detailed development guidance and [TODO.md](TODO.md) for planned features.
248
+
249
+ ## ๐Ÿ“š Documentation
250
+
251
+ This project features comprehensive documentation organized using the **Diรกtaxis framework** - a systematic approach that organizes content by user needs.
252
+
253
+ ### Documentation Structure
254
+
255
+ | | **PRACTICAL USE** | **THEORETICAL KNOWLEDGE** |
256
+ |-------------------|-----------------------------------|---------------------------------|
257
+ | **LEARNING-ORIENTED** | ๐Ÿ“š **TUTORIALS**<br>(Learning by doing) | ๐Ÿ“– **EXPLANATION**<br>(Understanding) |
258
+ | **PROBLEM-ORIENTED** | ๐Ÿ› ๏ธ **HOW-TO GUIDES**<br>(Solving problems) | ๐Ÿ“‹ **REFERENCE**<br>(Information lookup) |
259
+
260
+ ### Working with Documentation
261
+
262
+ ```bash
263
+ # Install documentation dependencies
264
+ uv pip install -e .[docs]
265
+
266
+ # Serve documentation locally (available at http://localhost:8000)
267
+ uv run mkdocs serve
268
+
269
+ # Build documentation for production
270
+ uv run mkdocs build
271
+
272
+ # Or use poe tasks
273
+ uv run poe docs-serve # Serve locally
274
+ uv run poe docs-build # Build for production
275
+ ```
276
+
277
+ The documentation includes tutorials, how-to guides, API reference, and conceptual explanations. Visit the documentation site for complete details.
278
+
279
+ ## License
280
+
281
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,62 @@
1
+ """
2
+ OANDA REST API v20 Python SDK
3
+
4
+ A simple, elegant Python client for OANDA's REST API v20.
5
+
6
+ Usage:
7
+ from fivetwenty import Client, AsyncClient, Environment, AccountConfig
8
+
9
+ # Method 1: Direct parameters
10
+ async with AsyncClient(token="your-token", environment=Environment.PRACTICE) as client:
11
+ accounts = await client.accounts.list()
12
+
13
+ # Method 2: Configuration object
14
+ config = AccountConfig(
15
+ token="your-token",
16
+ account_id="your-account-id",
17
+ environment=Environment.PRACTICE,
18
+ alias="my_account"
19
+ )
20
+ async with AsyncClient(config=config) as client:
21
+ accounts = await client.accounts.list()
22
+
23
+ # Method 3: Environment variables (fallback)
24
+ # Set FIVETWENTY_OANDA_TOKEN, FIVETWENTY_OANDA_ACCOUNT, etc.
25
+ async with AsyncClient() as client:
26
+ accounts = await client.accounts.list()
27
+
28
+ # Sync wrapper (same patterns)
29
+ with Client(token="your-token") as client:
30
+ accounts = client.accounts.list()
31
+ """
32
+
33
+ __version__ = "20.1.0"
34
+
35
+ from ._internal.environment import Environment
36
+ from .client import AsyncClient, Client
37
+ from .configuration import AccountConfig, AccountConfigLoader, ConfigValidator
38
+ from .exceptions import FiveTwentyError, StreamStall
39
+ from .models import ErrorCategory, ErrorDetails, ErrorSeverity, FiveTwentyErrorCode, ValidationViolation
40
+
41
+ __all__ = [
42
+ # Configuration
43
+ "AccountConfig",
44
+ "AccountConfigLoader",
45
+ # Main clients
46
+ "AsyncClient",
47
+ "Client",
48
+ "ConfigValidator",
49
+ # Enums
50
+ "Environment",
51
+ # Error handling
52
+ "ErrorCategory",
53
+ "ErrorDetails",
54
+ "ErrorSeverity",
55
+ # Exceptions
56
+ "FiveTwentyError",
57
+ "FiveTwentyErrorCode",
58
+ "StreamStall",
59
+ "ValidationViolation",
60
+ # Version
61
+ "__version__",
62
+ ]
@@ -0,0 +1 @@
1
+ """Internal utilities and helpers."""
@@ -0,0 +1,17 @@
1
+ """Environment configuration."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class Environment(Enum):
7
+ """OANDA API environments."""
8
+
9
+ PRACTICE = "practice"
10
+ LIVE = "live"
11
+
12
+ @property
13
+ def base_url(self) -> str:
14
+ """Get the base URL for this environment."""
15
+ if self == Environment.LIVE:
16
+ return "https://api-fxtrade.oanda.com/v3"
17
+ return "https://api-fxpractice.oanda.com/v3"