429 error handling

The LSEG historical pricing API (via either lseg.data.content.historical_pricing or lseg.data.get_history) appears to request all securities at once. This means that for large universes we are prone to generate 429 errors, since the backend is rate limited. It does not appear that the API has any handling for this nor any internal rate limiting?
When I run a simple request for e.g. the Russell 2000 and call get_history, numerous of the stocks are simply silently empty. However, if I call lseg.data.content.historical_pricing, I can see that the resulting response.errors object has hundreds of 429s. My current workaround for this involves parsing the 429 errors: see below.
Questions:
1) Is this the best workaround here? I suppose another option would be me individually making requests with the async API and writing my own rate limiter class, and then merging the DataFrames that result?
2) I'm sort of surprised that one function call of mine to the API leads the API to in turn do enough requests to generate unhandled 429s. I'd have thought the API would handle any internal rate limiting. Am I potentially doing something wrong in my definition?
3) When I request data using definition.get_data() and receive hundreds of 429s: some of those stocks that gave back 429s ALSO have non-null data associated with them. What does that mean and how am I to interpret that? Should I throw away that data or keep it?
Current Workaround:
def get_history_workaround(universe: list, **definition_kwargs): definition = hp.Definition(universe=universe, **definition_kwargs) data = pd.DataFrame() return_errors = [] ric_pattern = re.compile(r'Requested ric: (\S+)\. Requested fields:') while universe: response = definition.get_data() if data.empty: data = response.data.df else: for ric in universe: # Since we are assigning into a DataFrame, everything should have the same index # and we throw away additional dates from the smaller requests data[ric] = response.data.df[ric] universe = [] for error in response.data.errors: if error.code == 429 and (match := ric_pattern.search(error.message)): ric = match.group(1) universe.append(ric) del data[ric] else: return_errors.append(error) if universe: print(f'Received 429 for {len(universe)} RICs. Retrying...') definition = hp.Definition(universe=universe, **definition_kwargs) return data, return_errors
Answers
-
Thank you for reaching out to us.
Under the hood, the Historical Pricing APIs support one RIC at a time. Therefore, if the universe contains 1000 items, it will send 1000 requests to get historical data.
I checked the code and found that the library uses the ThreadPoolExecutor to manage those requests. I think this can trigger the "429 Too Many Requests" error when requesting a lot of items. The rate limit of the interday historical pricing is 50 requests per second.
According to this limit, you may need to request (calling the get_data method) at most 50 items at a time.
Because the endpoint supports one RIC at a time, you can keep the data if the request is successful.
0
Categories
- All Categories
- 3 Polls
- 6 AHS
- 36 Alpha
- 166 App Studio
- 6 Block Chain
- 4 Bot Platform
- 18 Connected Risk APIs
- 47 Data Fusion
- 34 Data Model Discovery
- 685 Datastream
- 1.4K DSS
- 615 Eikon COM
- 5.2K Eikon Data APIs
- 10 Electronic Trading
- Generic FIX
- 7 Local Bank Node API
- 3 Trading API
- 2.9K Elektron
- 1.4K EMA
- 252 ETA
- 556 WebSocket API
- 38 FX Venues
- 14 FX Market Data
- 1 FX Post Trade
- 1 FX Trading - Matching
- 12 FX Trading – RFQ Maker
- 5 Intelligent Tagging
- 2 Legal One
- 23 Messenger Bot
- 3 Messenger Side by Side
- 9 ONESOURCE
- 7 Indirect Tax
- 60 Open Calais
- 275 Open PermID
- 44 Entity Search
- 2 Org ID
- 1 PAM
- PAM - Logging
- 6 Product Insight
- Project Tracking
- ProView
- ProView Internal
- 22 RDMS
- 1.9K Refinitiv Data Platform
- 652 Refinitiv Data Platform Libraries
- 4 LSEG Due Diligence
- LSEG Due Diligence Portal API
- 4 Refinitiv Due Dilligence Centre
- Rose's Space
- 1.2K Screening
- 18 Qual-ID API
- 13 Screening Deployed
- 23 Screening Online
- 12 World-Check Customer Risk Screener
- 1K World-Check One
- 46 World-Check One Zero Footprint
- 45 Side by Side Integration API
- 2 Test Space
- 3 Thomson One Smart
- 10 TR Knowledge Graph
- 151 Transactions
- 143 REDI API
- 1.8K TREP APIs
- 4 CAT
- 27 DACS Station
- 121 Open DACS
- 1.1K RFA
- 104 UPA
- 193 TREP Infrastructure
- 228 TRKD
- 917 TRTH
- 5 Velocity Analytics
- 9 Wealth Management Web Services
- 90 Workspace SDK
- 11 Element Framework
- 5 Grid
- 18 World-Check Data File
- 1 Yield Book Analytics
- 46 中文论坛