bugfixing
This commit is contained in:
parent
27d8958e7c
commit
19f2ff0965
106
app/main.py
106
app/main.py
@ -1313,6 +1313,10 @@ async def get_indicator(data: IndicatorListData, api_key: str = Security(get_api
|
||||
# Only merge screener data for keys that are not price, volume, or changesPercentage
|
||||
result.update(screener_dict[symbol])
|
||||
|
||||
# Ensure all keys in rule_of_list are present, setting missing ones to None
|
||||
for result in combined_results:
|
||||
for key in rule_of_list:
|
||||
result.setdefault(key, None)
|
||||
|
||||
# Serialize and compress the response
|
||||
res = orjson.dumps(combined_results)
|
||||
@ -1325,9 +1329,8 @@ async def get_indicator(data: IndicatorListData, api_key: str = Security(get_api
|
||||
)
|
||||
|
||||
|
||||
|
||||
async def process_watchlist_ticker(ticker, rule_of_list, quote_keys_to_include, screener_dict, etf_set):
|
||||
"""Optimized single ticker processing with reduced I/O and memory overhead."""
|
||||
"""Optimized single ticker processing with guaranteed rule_of_list keys."""
|
||||
ticker = ticker.upper()
|
||||
ticker_type = 'stocks'
|
||||
if ticker in etf_set:
|
||||
@ -1341,113 +1344,92 @@ async def process_watchlist_ticker(ticker, rule_of_list, quote_keys_to_include,
|
||||
load_json_async(f"json/earnings/next/{ticker}.json")
|
||||
)
|
||||
except Exception:
|
||||
# Gracefully handle missing files
|
||||
return None, [], None
|
||||
|
||||
# Early return if no quote data
|
||||
if not quote_dict:
|
||||
return None, [], None
|
||||
|
||||
# Optimized quote filtering with dict comprehension
|
||||
# Merge data from multiple sources
|
||||
filtered_quote = {
|
||||
key: quote_dict.get(key)
|
||||
for key in rule_of_list + quote_keys_to_include
|
||||
if key in quote_dict
|
||||
}
|
||||
|
||||
# Efficiently add core quote data
|
||||
# Add core fields with priority to quote data
|
||||
core_keys = ['price', 'volume', 'changesPercentage', 'symbol']
|
||||
for key in core_keys:
|
||||
if key in quote_dict:
|
||||
filtered_quote[key] = quote_dict[key]
|
||||
filtered_quote.update({k: quote_dict[k] for k in core_keys if k in quote_dict})
|
||||
|
||||
# Merge screener data for non-core fields
|
||||
symbol = filtered_quote.get('symbol')
|
||||
if symbol and symbol in screener_dict:
|
||||
filtered_quote.update({
|
||||
k: v for k, v in screener_dict[symbol].items()
|
||||
if k not in filtered_quote
|
||||
})
|
||||
|
||||
# Ensure all rule_of_list keys exist with None as default
|
||||
for key in rule_of_list:
|
||||
filtered_quote.setdefault(key, None)
|
||||
|
||||
filtered_quote['type'] = ticker_type
|
||||
|
||||
# Efficient screener data merge
|
||||
symbol = filtered_quote.get('symbol')
|
||||
if symbol and symbol in screener_dict:
|
||||
# Use dict.update() for faster merging
|
||||
screener_data = {
|
||||
k: v for k, v in screener_dict[symbol].items()
|
||||
if k not in filtered_quote
|
||||
}
|
||||
filtered_quote.update(screener_data)
|
||||
|
||||
# Lightweight news processing
|
||||
# Process supplemental data
|
||||
news = [
|
||||
{k: v for k, v in item.items() if k not in ['image', 'text']}
|
||||
for item in (news_dict or [])[:5]
|
||||
]
|
||||
|
||||
# Compact earnings processing
|
||||
earnings = {**earnings_dict, 'symbol': symbol} if earnings_dict else None
|
||||
|
||||
return filtered_quote, news, earnings
|
||||
|
||||
@app.post("/get-watchlist")
|
||||
async def get_watchlist(data: GetWatchList, api_key: str = Security(get_api_key)):
|
||||
"""Further optimized watchlist endpoint with concurrent processing."""
|
||||
"""Optimized endpoint with complete key enforcement."""
|
||||
try:
|
||||
watchlist = pb.collection("watchlist").get_one(data.watchListId)
|
||||
ticker_list = watchlist.ticker
|
||||
except Exception:
|
||||
raise HTTPException(status_code=404, detail="Watchlist not found")
|
||||
|
||||
# Predefined configurations
|
||||
quote_keys_to_include = ['volume', 'marketCap', 'changesPercentage', 'price', 'symbol', 'name']
|
||||
# Configure data collection parameters
|
||||
rule_of_list = list(set(
|
||||
(data.ruleOfList or []) +
|
||||
['symbol', 'name']
|
||||
['symbol', 'name'] # Ensure mandatory fields
|
||||
))
|
||||
quote_keys_to_include = ['volume', 'marketCap', 'changesPercentage', 'price']
|
||||
|
||||
# Prepare screener dictionary with efficient lookup
|
||||
# Preprocess screener data for O(1) lookups
|
||||
screener_dict = {
|
||||
item['symbol']: {
|
||||
key: item.get(key)
|
||||
for key in rule_of_list if key in item
|
||||
}
|
||||
item['symbol']: {k: item.get(k) for k in rule_of_list if k in item}
|
||||
for item in stock_screener_data
|
||||
}
|
||||
|
||||
# Use concurrent processing with more efficient method
|
||||
results_and_extras = await asyncio.gather(
|
||||
*[
|
||||
process_watchlist_ticker(
|
||||
ticker,
|
||||
rule_of_list,
|
||||
quote_keys_to_include,
|
||||
screener_dict,
|
||||
etf_set, # Assuming these are pre-computed sets
|
||||
)
|
||||
for ticker in ticker_list
|
||||
]
|
||||
)
|
||||
# Parallel processing pipeline
|
||||
results = await asyncio.gather(*[
|
||||
process_watchlist_ticker(
|
||||
ticker,
|
||||
rule_of_list,
|
||||
quote_keys_to_include,
|
||||
screener_dict,
|
||||
etf_set
|
||||
) for ticker in ticker_list
|
||||
])
|
||||
|
||||
# Efficient list comprehensions for filtering
|
||||
combined_results = [result for result in (r[0] for r in results_and_extras) if result]
|
||||
combined_news = [
|
||||
news_item
|
||||
for news_list in (r[1] for r in results_and_extras)
|
||||
for news_item in news_list
|
||||
]
|
||||
combined_earnings = [earnings for earnings in (r[2] for r in results_and_extras) if earnings]
|
||||
|
||||
# Use orjson for faster JSON serialization
|
||||
res = {
|
||||
'data': combined_results,
|
||||
'news': combined_news,
|
||||
'earnings': combined_earnings
|
||||
# Efficient response assembly
|
||||
response_data = {
|
||||
'data': [r[0] for r in results if r[0]],
|
||||
'news': [item for r in results for item in r[1]],
|
||||
'earnings': [r[2] for r in results if r[2]]
|
||||
}
|
||||
|
||||
# Compress efficiently
|
||||
compressed_data = gzip.compress(orjson.dumps(res), compresslevel=6)
|
||||
|
||||
return StreamingResponse(
|
||||
io.BytesIO(compressed_data),
|
||||
io.BytesIO(gzip.compress(orjson.dumps(response_data))),
|
||||
media_type="application/json",
|
||||
headers={"Content-Encoding": "gzip"}
|
||||
)
|
||||
|
||||
|
||||
@app.post("/get-price-alert")
|
||||
async def get_price_alert(data: dict, api_key: str = Security(get_api_key)):
|
||||
user_id = data.get('userId')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user