@farazirfan/costar-server-executor 1.7.26 → 1.7.28

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.
@@ -0,0 +1,332 @@
1
+ # Saxo API Reference
2
+
3
+ > Agent-editable. Add notes about endpoints, quirks, rate limits as you discover them.
4
+
5
+ Complete reference for Saxo OpenAPI endpoints using `saxo_openapi` Python package.
6
+
7
+ ## Client Setup
8
+
9
+ ```python
10
+ import saxo_openapi
11
+ import os
12
+
13
+ client = saxo_openapi.API(
14
+ access_token=os.environ['SAXO_ACCESS_TOKEN'],
15
+ environment='simulation' # or 'live'
16
+ )
17
+ ```
18
+
19
+ ## Root Services (Account Info)
20
+
21
+ ### User Details
22
+
23
+ Get authenticated user information:
24
+
25
+ ```python
26
+ import saxo_openapi.endpoints.rootservices as rs
27
+
28
+ r = rs.user.UserDetails()
29
+ client.request(r)
30
+
31
+ # Returns:
32
+ # - ClientKey
33
+ # - Name
34
+ # - Accounts (list with AccountKey, AccountType, Currency)
35
+ ```
36
+
37
+ ### Client Details
38
+
39
+ ```python
40
+ r = rs.client.ClientDetails(ClientKey=client_key)
41
+ client.request(r)
42
+ ```
43
+
44
+ ## Portfolio Endpoints
45
+
46
+ ### Account Balances
47
+
48
+ ```python
49
+ import saxo_openapi.endpoints.portfolio as pf
50
+
51
+ r = pf.balances.AccountBalances(params={'ClientKey': client_key})
52
+ client.request(r)
53
+
54
+ # Returns:
55
+ # - TotalValue
56
+ # - CashBalance
57
+ # - MarginAvailableForTrading
58
+ # - MarginUtilizationPct
59
+ # - UnrealizedPositionsValue
60
+ ```
61
+
62
+ ### Positions
63
+
64
+ ```python
65
+ # All positions
66
+ r = pf.positions.PositionsMe()
67
+ client.request(r)
68
+
69
+ # Specific position
70
+ r = pf.positions.PositionDetails(PositionId=position_id)
71
+ client.request(r)
72
+
73
+ # Returns:
74
+ # - PositionId
75
+ # - Uic, AssetType
76
+ # - Amount (positive = long, negative = short)
77
+ # - OpenPrice, CurrentPrice
78
+ # - ProfitLossOnTrade
79
+ # - MarginUsedIncludingPendingOrders
80
+ ```
81
+
82
+ ### Exposure
83
+
84
+ ```python
85
+ # Net exposure across all positions
86
+ r = pf.netpositions.NetPositionsMe()
87
+ client.request(r)
88
+ ```
89
+
90
+ ## Trading Endpoints
91
+
92
+ ### Place Order
93
+
94
+ ```python
95
+ import saxo_openapi.endpoints.trading as tr
96
+
97
+ order_data = {
98
+ 'AccountKey': account_key,
99
+ 'Uic': 21,
100
+ 'AssetType': 'FxSpot',
101
+ 'BuySell': 'Buy',
102
+ 'Amount': 10000,
103
+ 'OrderType': 'Market',
104
+ 'OrderDuration': {'DurationType': 'DayOrder'}
105
+ }
106
+
107
+ r = tr.orders.Order(data=order_data)
108
+ client.request(r)
109
+
110
+ # Success: status_code 201
111
+ # Response contains OrderId
112
+ ```
113
+
114
+ ### Order Status
115
+
116
+ ```python
117
+ # All orders
118
+ r = tr.orders.OrdersMe()
119
+ client.request(r)
120
+
121
+ # Specific order
122
+ r = tr.orders.OrderDetails(OrderId=order_id)
123
+ client.request(r)
124
+
125
+ # Returns:
126
+ # - OrderId
127
+ # - Status: Working, Filled, Cancelled, Rejected
128
+ # - FilledAmount
129
+ # - ExecutionTimeOpen
130
+ ```
131
+
132
+ ### Cancel Order
133
+
134
+ ```python
135
+ r = tr.orders.CancelOrder(AccountKey=account_key, OrderId=order_id)
136
+ client.request(r)
137
+
138
+ # Success: status_code 200 or 202
139
+ ```
140
+
141
+ ### Modify Order
142
+
143
+ ```python
144
+ # Update order price or duration
145
+ r = tr.orders.ModifyOrder(
146
+ AccountKey=account_key,
147
+ OrderId=order_id,
148
+ data={'OrderPrice': 1.0860}
149
+ )
150
+ client.request(r)
151
+ ```
152
+
153
+ ### Info Prices (Real-Time Quotes)
154
+
155
+ ```python
156
+ r = tr.prices.InfoPrice(Uic=21, AssetType='FxSpot')
157
+ client.request(r)
158
+
159
+ # Returns:
160
+ # - Quote: {Bid, Ask, Mid}
161
+ # - PriceInfo: {High, Low, NetChange}
162
+ # - InstrumentPriceDetails: {IsMarketOpen, ValueDate}
163
+ ```
164
+
165
+ ## Reference Data
166
+
167
+ ### Search Instruments
168
+
169
+ ```python
170
+ import saxo_openapi.endpoints.referencedata as rd
171
+
172
+ params = {
173
+ 'Keywords': 'EURUSD',
174
+ 'AssetTypes': 'FxSpot',
175
+ 'limit': 20
176
+ }
177
+ r = rd.instruments.Instruments(params=params)
178
+ client.request(r)
179
+
180
+ # Returns array with:
181
+ # - Identifier (Uic)
182
+ # - Symbol
183
+ # - Description
184
+ # - AssetType
185
+ # - ExchangeId
186
+ ```
187
+
188
+ ### Instrument Details
189
+
190
+ ```python
191
+ r = rd.instruments.InstrumentDetails(Uic=21, AssetType='FxSpot')
192
+ client.request(r)
193
+
194
+ # Returns:
195
+ # - MinimumTradeSize
196
+ # - TickSize
197
+ # - ContractSize
198
+ # - TradingStatus
199
+ # - Format (price decimals)
200
+ ```
201
+
202
+ ### Exchanges
203
+
204
+ ```python
205
+ r = rd.exchanges.ExchangeList()
206
+ client.request(r)
207
+ ```
208
+
209
+ ## Chart Data
210
+
211
+ ### Historical Candles
212
+
213
+ ```python
214
+ import saxo_openapi.endpoints.chart as ch
215
+
216
+ params = {
217
+ 'Uic': 21,
218
+ 'AssetType': 'FxSpot',
219
+ 'Horizon': 60, # 1-hour candles
220
+ 'Count': 100 # Last 100 candles
221
+ }
222
+ r = ch.charts.Charts(params=params)
223
+ client.request(r)
224
+
225
+ # Returns array of candles with:
226
+ # - Time (Unix timestamp)
227
+ # - Open, High, Low, Close
228
+ # - Volume (if available)
229
+ ```
230
+
231
+ **Horizon Values:**
232
+ - `1` — 1 minute
233
+ - `5` — 5 minutes
234
+ - `15` — 15 minutes
235
+ - `60` — 1 hour
236
+ - `1440` — 1 day
237
+ - `10080` — 1 week
238
+
239
+ ## Request/Response Format
240
+
241
+ All API calls follow the same pattern:
242
+
243
+ ```python
244
+ # 1. Create request object
245
+ r = module.endpoint.Method(params={...})
246
+
247
+ # 2. Execute request
248
+ client.request(r)
249
+
250
+ # 3. Check status
251
+ if r.status_code == 200: # or 201 for orders
252
+ data = r.response
253
+ else:
254
+ error = r.response # Error details
255
+ ```
256
+
257
+ ## Error Handling
258
+
259
+ ```python
260
+ try:
261
+ client.request(r)
262
+ except saxo_openapi.exceptions.OpenAPIError as e:
263
+ print(f"API Error: {e}")
264
+ print(f"Status: {e.status_code}")
265
+ print(f"Message: {e.message}")
266
+ except Exception as e:
267
+ print(f"Unexpected error: {e}")
268
+ ```
269
+
270
+ ## Common Errors
271
+
272
+ | Error Code | Message | Cause | Solution |
273
+ |-----------|---------|-------|----------|
274
+ | 401 | Unauthorized | Invalid/expired token | Refresh token |
275
+ | 400 | Bad Request | Invalid parameters | Check order data |
276
+ | 403 | Forbidden | Insufficient permissions | Check account permissions |
277
+ | 429 | Too Many Requests | Rate limit exceeded | Slow down requests |
278
+ | 500 | Internal Server Error | Saxo server issue | Retry with backoff |
279
+
280
+ ## Rate Limits
281
+
282
+ Saxo enforces rate limits per endpoint category:
283
+
284
+ | Category | Limit | Window |
285
+ |----------|-------|--------|
286
+ | **Trading** (orders) | 100 req | 1 minute |
287
+ | **Portfolio** | 300 req | 1 minute |
288
+ | **Prices** | 100 req | 1 minute |
289
+ | **Chart** | 50 req | 1 minute |
290
+
291
+ **Best Practices:**
292
+ - Cache instrument searches (Uic lookup)
293
+ - Batch position/order queries when possible
294
+ - Use WebSocket for real-time prices (not polling)
295
+ - Implement exponential backoff on 429 errors
296
+
297
+ ## WebSocket Streaming (Advanced)
298
+
299
+ For real-time price feeds, use WebSocket streaming:
300
+
301
+ ```python
302
+ # TODO: Agent should research and implement WebSocket streaming
303
+ # when polling becomes a bottleneck or rate limits are hit.
304
+ # See saxo_openapi documentation for streaming setup.
305
+ ```
306
+
307
+ ## Response Caching
308
+
309
+ Cache responses that don't change frequently:
310
+
311
+ ```python
312
+ # Cache instrument details (rarely change)
313
+ instrument_cache = {}
314
+
315
+ def get_instrument_details(uic, asset_type):
316
+ key = f"{uic}:{asset_type}"
317
+ if key not in instrument_cache:
318
+ r = rd.instruments.InstrumentDetails(Uic=uic, AssetType=asset_type)
319
+ client.request(r)
320
+ instrument_cache[key] = r.response
321
+ return instrument_cache[key]
322
+ ```
323
+
324
+ ## Agent Evolution Notes
325
+
326
+ *(Add discoveries here as you use the API)*
327
+
328
+ - Which endpoints are most rate-limited?
329
+ - Best practices for batching requests?
330
+ - WebSocket setup and benefits
331
+ - Caching strategies that work
332
+ - Error patterns and how to handle them
@@ -0,0 +1,249 @@
1
+ # Saxo Asset Classes
2
+
3
+ > Agent-editable. Add notes about instruments you trade, quirks, best practices.
4
+
5
+ Saxo covers 71,000+ instruments across all major asset classes except crypto.
6
+
7
+ ## Asset Type Codes
8
+
9
+ Saxo uses string codes for asset types. Always specify the correct `AssetType` in orders and queries.
10
+
11
+ | Asset Type Code | Description | Examples |
12
+ |----------------|-------------|----------|
13
+ | `FxSpot` | Spot Forex | EURUSD, GBPJPY, XAUUSD, XAGUSD |
14
+ | `FxForwards` | Forex Forwards | Long-dated forex contracts |
15
+ | `Stock` | Individual Stocks | AAPL, TSLA, VOO |
16
+ | `StockIndex` | Stock Indexes | S&P 500, DAX |
17
+ | `CfdOnStock` | Stock CFDs | Leveraged stock trading |
18
+ | `CfdOnIndex` | Index CFDs | Leveraged index trading |
19
+ | `CfdOnFutures` | Futures CFDs | Oil, gold futures |
20
+ | `Bond` | Bonds | US Treasuries, corporate bonds |
21
+ | `StockOption` | Equity Options | Call/put options on stocks |
22
+ | `FxOption` | FX Options | Currency options |
23
+ | `ContractFutures` | Futures Contracts | Commodities, indexes |
24
+
25
+ ## Forex (FxSpot)
26
+
27
+ **Trading Hours:** 24/5 (Sunday 5pm ET — Friday 5pm ET)
28
+
29
+ ### Major Pairs (Highest Liquidity)
30
+
31
+ | Pair | Uic | Description | Typical Spread | Sessions |
32
+ |------|-----|-------------|---------------|----------|
33
+ | EURUSD | 21 | Euro vs US Dollar | 0.1-0.5 pips | All |
34
+ | GBPUSD | 22 | British Pound vs USD | 0.5-1.5 pips | London, NY |
35
+ | USDJPY | 23 | US Dollar vs Japanese Yen | 0.2-0.8 pips | Tokyo, NY |
36
+ | USDCHF | 24 | USD vs Swiss Franc | 0.5-1.5 pips | All |
37
+
38
+ ### Commodities (via FxSpot)
39
+
40
+ | Pair | Uic | Description | Contract Size | Notes |
41
+ |------|-----|-------------|--------------|-------|
42
+ | XAUUSD | 1639 | Gold vs USD | 1 troy ounce | Most liquid |
43
+ | XAGUSD | 1640 | Silver vs USD | 1 troy ounce | Higher volatility |
44
+ | XPTUSD | — | Platinum vs USD | 1 troy ounce | Lower liquidity |
45
+ | XPDUSD | — | Palladium vs USD | 1 troy ounce | Lower liquidity |
46
+
47
+ **Key Points:**
48
+ - Amount is in base currency units (EURUSD 10000 = 10k EUR)
49
+ - Price quoted to 4-5 decimal places (pipettes)
50
+ - Leverage typically 50:1 to 500:1 (check account settings)
51
+ - Spreads widen during low liquidity (Asian session, holidays, news)
52
+ - Best execution during session overlaps (London/NY)
53
+
54
+ **Search Example:**
55
+ ```python
56
+ params = {'Keywords': 'EURUSD', 'AssetTypes': 'FxSpot'}
57
+ r = rd.instruments.Instruments(params=params)
58
+ client.request(r)
59
+ ```
60
+
61
+ ## Stocks
62
+
63
+ **Trading Hours:** Exchange-specific (NYSE: 9:30am-4pm ET, etc.)
64
+
65
+ ### Search by Exchange
66
+
67
+ ```python
68
+ # Search US stocks
69
+ params = {'Keywords': 'AAPL', 'AssetTypes': 'Stock', 'ExchangeId': 'NASDAQ'}
70
+ r = rd.instruments.Instruments(params=params)
71
+ client.request(r)
72
+ ```
73
+
74
+ **Key Points:**
75
+ - Amount is number of shares (integer for most, can be fractional for some)
76
+ - Price in exchange currency (USD for US stocks, EUR for EU, etc.)
77
+ - Leverage typically 4:1 to 10:1 (much lower than forex)
78
+ - Commissions per trade (not just spread)
79
+ - Check market hours — many exchanges have breaks or early closes
80
+ - Extended hours available for some exchanges (pre-market, after-hours)
81
+
82
+ **Common Exchanges:**
83
+ - `NASDAQ` — US tech stocks (AAPL, MSFT, TSLA)
84
+ - `NYSE` — US stocks (traditional companies)
85
+ - `XETRA` — German stocks (DAX components)
86
+ - `LSE` — London Stock Exchange
87
+
88
+ ## CFDs (Contracts for Difference)
89
+
90
+ CFDs allow leveraged trading without owning the underlying asset.
91
+
92
+ ### Stock CFDs
93
+
94
+ ```python
95
+ params = {'Keywords': 'AAPL', 'AssetTypes': 'CfdOnStock'}
96
+ r = rd.instruments.Instruments(params=params)
97
+ client.request(r)
98
+ ```
99
+
100
+ **Key Points:**
101
+ - Higher leverage than stocks (up to 20:1)
102
+ - No ownership — purely price speculation
103
+ - Overnight financing costs (rollover fees)
104
+ - Lower capital requirements
105
+ - Some jurisdictions restrict CFD trading
106
+
107
+ ### Index CFDs
108
+
109
+ Trade stock indexes with leverage:
110
+
111
+ ```python
112
+ params = {'Keywords': 'S&P 500', 'AssetTypes': 'CfdOnIndex'}
113
+ r = rd.instruments.Instruments(params=params)
114
+ client.request(r)
115
+ ```
116
+
117
+ **Popular Indexes:**
118
+ - SPX500 (S&P 500)
119
+ - NAS100 (Nasdaq 100)
120
+ - US30 (Dow Jones)
121
+ - GER40 (DAX)
122
+
123
+ ## Bonds
124
+
125
+ Fixed-income securities. Lower volatility than stocks or forex.
126
+
127
+ ```python
128
+ params = {'Keywords': 'US Treasury', 'AssetTypes': 'Bond'}
129
+ r = rd.instruments.Instruments(params=params)
130
+ client.request(r)
131
+ ```
132
+
133
+ **Key Points:**
134
+ - Price quoted as percentage of par value
135
+ - Yields move inverse to prices
136
+ - Lower leverage (typically 2:1 to 5:1)
137
+ - Less volatile — good for capital preservation
138
+ - Interest rate sensitivity (duration)
139
+
140
+ ## Options
141
+
142
+ Complex derivatives. High risk, high reward.
143
+
144
+ ### Stock Options
145
+
146
+ ```python
147
+ params = {'Keywords': 'AAPL', 'AssetTypes': 'StockOption'}
148
+ r = rd.instruments.Instruments(params=params)
149
+ client.request(r)
150
+ ```
151
+
152
+ **Key Points:**
153
+ - Call = right to buy, Put = right to sell
154
+ - Strike price and expiration date critical
155
+ - Theta decay — options lose value over time
156
+ - Implied volatility affects pricing
157
+ - Can lose 100% of premium
158
+ - Require options trading approval
159
+
160
+ ### FX Options
161
+
162
+ ```python
163
+ params = {'Keywords': 'EURUSD', 'AssetTypes': 'FxOption'}
164
+ r = rd.instruments.Instruments(params=params)
165
+ client.request(r)
166
+ ```
167
+
168
+ ## Futures
169
+
170
+ Contracts for future delivery of assets.
171
+
172
+ ```python
173
+ params = {'Keywords': 'Crude Oil', 'AssetTypes': 'ContractFutures'}
174
+ r = rd.instruments.Instruments(params=params)
175
+ client.request(r)
176
+ ```
177
+
178
+ **Key Points:**
179
+ - Expiration dates — must close or roll before expiry
180
+ - High leverage (10:1 to 50:1)
181
+ - Margin calls if position moves against you
182
+ - Contango/backwardation in commodity futures
183
+ - Each contract has specific size (e.g., 1000 barrels of oil)
184
+
185
+ ## Instrument Discovery
186
+
187
+ Always search before trading to get correct Uic:
188
+
189
+ ```python
190
+ import saxo_openapi.endpoints.referencedata as rd
191
+
192
+ # General search
193
+ params = {
194
+ 'Keywords': 'gold',
195
+ 'AssetTypes': 'FxSpot,CfdOnFutures',
196
+ 'limit': 20
197
+ }
198
+ r = rd.instruments.Instruments(params=params)
199
+ client.request(r)
200
+
201
+ # Get instrument details
202
+ for inst in r.response['Data']:
203
+ print(f"{inst['Symbol']}: Uic={inst['Identifier']}, Type={inst['AssetType']}")
204
+ ```
205
+
206
+ ## Product Details
207
+
208
+ Before trading any instrument, check its details:
209
+
210
+ ```python
211
+ import saxo_openapi.endpoints.referencedata as rd
212
+
213
+ r = rd.instruments.InstrumentDetails(Uic=21, AssetType='FxSpot')
214
+ client.request(r)
215
+
216
+ # Returns:
217
+ # - MinimumTradeSize
218
+ # - TickSize (price increment)
219
+ # - ContractSize
220
+ # - TradingStatus
221
+ # - TradingHours
222
+ # - MarginRequirement
223
+ ```
224
+
225
+ ## Session Times (Critical for Forex/Commodities)
226
+
227
+ | Session | Hours (ET) | Best For |
228
+ |---------|-----------|----------|
229
+ | **Tokyo** | 7pm - 4am | JPY pairs |
230
+ | **London** | 3am - 12pm | EUR, GBP pairs |
231
+ | **New York** | 8am - 5pm | USD pairs |
232
+ | **Overlap (London/NY)** | 8am - 12pm | Highest liquidity |
233
+
234
+ **Avoid:**
235
+ - Sunday open (5pm ET) — low liquidity, wide spreads
236
+ - Friday close (5pm ET) — position squaring, unpredictable
237
+ - Major holidays — Christmas, New Year, etc.
238
+ - Low-liquidity hours — 5pm-7pm ET (Sydney only)
239
+
240
+ ## Agent Evolution Notes
241
+
242
+ *(Add discoveries here as you trade different instruments)*
243
+
244
+ - Best instruments for each strategy
245
+ - Liquidity patterns: which sessions, which instruments?
246
+ - Spread behavior: when do spreads widen?
247
+ - Margin surprises: instruments with unexpectedly high requirements?
248
+ - Correlation discoveries: which instruments move together?
249
+ - Session-specific edges: patterns that only work in certain sessions?