diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1c8bd..939ef5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to the Adanos Python SDK will be documented in this file. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html) +## [2.7.0] - 2026-08-09 + +### Added +- Synced generated model coverage with Adanos Market Sentiment API `1.49.0`, including Polymarket ticker `pulse`, daily bullish/bearish percentages, and structured compare/unsupported-asset errors. + +### Changed +- Polymarket market-level `unique_traders` is nullable when retained wallet-level trades do not cover the requested window. +- X/Twitter trending `trend` now uses the documented `rising` / `falling` / `stable` enum. +- Documented stable per-UTC-day `trend_history` semantics from API `1.48.1`. + ## [2.6.0] - 2026-06-23 ### Added diff --git a/README.md b/README.md index f7371d0..514595d 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,11 @@ Polymarket semantics: - `buzz_score` is activity-first and optimized for current market attention - `total_liquidity` is a windowed signal over the selected period - `current_market_count` is the live-only active-market breadth; `market_count` remains the selected-window breadth -- `top_mentions` on `stock()` are relevance-sorted by trading activity first +- `unique_traders` can be `None` when retained wallet-level trades do not fully cover the requested window +- `pulse` on `stock()` provides a compact current interpretation; use its evidence and warnings as data-quality context +- `top_mentions` on `stock()` are representative sentiment evidence, with directional markets prioritized + +Across platforms, each `trend_history` value represents its own UTC calendar day. The final value for a live window describes the current partial UTC day and is not expected to equal the top-level period `buzz_score`. ### Reddit Crypto diff --git a/src/adanos/__init__.py b/src/adanos/__init__.py index bbea4ff..19448cd 100644 --- a/src/adanos/__init__.py +++ b/src/adanos/__init__.py @@ -1,6 +1,6 @@ """Adanos Market Sentiment API — Python SDK.""" -__version__ = "2.6.0" +__version__ = "2.7.0" from ._wrapper import AdanosClient, StockSentimentClient diff --git a/src/adanos/_generated/api/news_stocks/compare_news_stocks.py b/src/adanos/_generated/api/news_stocks/compare_news_stocks.py index 4f5f6f6..ffe8bd8 100644 --- a/src/adanos/_generated/api/news_stocks/compare_news_stocks.py +++ b/src/adanos/_generated/api/news_stocks/compare_news_stocks.py @@ -5,6 +5,7 @@ from ... import errors from ...client import AuthenticatedClient, Client +from ...models.compare_limit_error import CompareLimitError from ...models.error_response import ErrorResponse from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError @@ -58,7 +59,7 @@ def _parse_response( return response_200 if response.status_code == 400: - response_400 = cast(Any, None) + response_400 = CompareLimitError.from_dict(response.json()) return response_400 if response.status_code == 401: @@ -79,7 +80,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_market_sentiment.py b/src/adanos/_generated/api/news_stocks/get_news_market_sentiment.py index 348f59a..3b32269 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_market_sentiment.py +++ b/src/adanos/_generated/api/news_stocks/get_news_market_sentiment.py @@ -66,7 +66,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_stock_explanation.py b/src/adanos/_generated/api/news_stocks/get_news_stock_explanation.py index 86ef88d..6ae44c9 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_stock_explanation.py +++ b/src/adanos/_generated/api/news_stocks/get_news_stock_explanation.py @@ -65,7 +65,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_stock_mentions.py b/src/adanos/_generated/api/news_stocks/get_news_stock_mentions.py index 454b05a..ca4eaf4 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_stock_mentions.py +++ b/src/adanos/_generated/api/news_stocks/get_news_stock_mentions.py @@ -76,7 +76,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_stock_sentiment.py b/src/adanos/_generated/api/news_stocks/get_news_stock_sentiment.py index 4601327..202c506 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_stock_sentiment.py +++ b/src/adanos/_generated/api/news_stocks/get_news_stock_sentiment.py @@ -10,6 +10,7 @@ from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError from ...models.invalid_period_error import InvalidPeriodError +from ...models.unsupported_asset_error import UnsupportedAssetError from ...models.news_stock_sentiment import NewsStockSentiment from ...types import UNSET, Response, Unset @@ -69,7 +70,7 @@ def _parse_response( return response_403 if response.status_code == 404: - response_404 = cast(Any, None) + response_404 = UnsupportedAssetError.from_dict(response.json()) return response_404 if response.status_code == 422: @@ -80,7 +81,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_trending_countries.py b/src/adanos/_generated/api/news_stocks/get_news_trending_countries.py index a914bf7..cf86972 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_trending_countries.py +++ b/src/adanos/_generated/api/news_stocks/get_news_trending_countries.py @@ -95,7 +95,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_trending_sectors.py b/src/adanos/_generated/api/news_stocks/get_news_trending_sectors.py index 4a99aaf..efcceb3 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_trending_sectors.py +++ b/src/adanos/_generated/api/news_stocks/get_news_trending_sectors.py @@ -95,7 +95,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/get_news_trending_stocks.py b/src/adanos/_generated/api/news_stocks/get_news_trending_stocks.py index 8f2c787..5a7a2c6 100644 --- a/src/adanos/_generated/api/news_stocks/get_news_trending_stocks.py +++ b/src/adanos/_generated/api/news_stocks/get_news_trending_stocks.py @@ -108,7 +108,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/news_stocks/search_news_stocks.py b/src/adanos/_generated/api/news_stocks/search_news_stocks.py index 19cba94..c958553 100644 --- a/src/adanos/_generated/api/news_stocks/search_news_stocks.py +++ b/src/adanos/_generated/api/news_stocks/search_news_stocks.py @@ -64,7 +64,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/compare_polymarket_stocks.py b/src/adanos/_generated/api/polymarket_stocks/compare_polymarket_stocks.py index 7ca0add..9c66721 100644 --- a/src/adanos/_generated/api/polymarket_stocks/compare_polymarket_stocks.py +++ b/src/adanos/_generated/api/polymarket_stocks/compare_polymarket_stocks.py @@ -5,6 +5,7 @@ from ... import errors from ...client import AuthenticatedClient, Client +from ...models.compare_limit_error import CompareLimitError from ...models.error_response import ErrorResponse from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError @@ -58,7 +59,7 @@ def _parse_response( return response_200 if response.status_code == 400: - response_400 = cast(Any, None) + response_400 = CompareLimitError.from_dict(response.json()) return response_400 if response.status_code == 401: @@ -79,7 +80,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_market_sentiment.py b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_market_sentiment.py index b39a0fb..1bc89d7 100644 --- a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_market_sentiment.py +++ b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_market_sentiment.py @@ -74,7 +74,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock.py b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock.py index 923e7c7..04640e6 100644 --- a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock.py +++ b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock.py @@ -11,6 +11,7 @@ from ...models.http_validation_error import HTTPValidationError from ...models.invalid_period_error import InvalidPeriodError from ...models.polymarket_stock_detail_response import PolymarketStockDetailResponse +from ...models.unsupported_asset_error import UnsupportedAssetError from ...types import UNSET, Response, Unset @@ -69,7 +70,7 @@ def _parse_response( return response_403 if response.status_code == 404: - response_404 = cast(Any, None) + response_404 = UnsupportedAssetError.from_dict(response.json()) return response_404 if response.status_code == 422: @@ -80,7 +81,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock_raw_mentions.py b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock_raw_mentions.py index be20aef..747d17d 100644 --- a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock_raw_mentions.py +++ b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_stock_raw_mentions.py @@ -76,7 +76,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_countries.py b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_countries.py index e47afc4..2f70e0a 100644 --- a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_countries.py +++ b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_countries.py @@ -84,7 +84,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_sectors.py b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_sectors.py index b48f699..e1161e8 100644 --- a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_sectors.py +++ b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_sectors.py @@ -84,7 +84,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_stocks.py b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_stocks.py index 6dbbba3..00290cd 100644 --- a/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_stocks.py +++ b/src/adanos/_generated/api/polymarket_stocks/get_polymarket_trending_stocks.py @@ -97,7 +97,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/polymarket_stocks/search_polymarket_stocks.py b/src/adanos/_generated/api/polymarket_stocks/search_polymarket_stocks.py index 86f7b02..61aee10 100644 --- a/src/adanos/_generated/api/polymarket_stocks/search_polymarket_stocks.py +++ b/src/adanos/_generated/api/polymarket_stocks/search_polymarket_stocks.py @@ -67,7 +67,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_crypto/compare_reddit_crypto_tokens.py b/src/adanos/_generated/api/reddit_crypto/compare_reddit_crypto_tokens.py index 285d079..2c6b477 100644 --- a/src/adanos/_generated/api/reddit_crypto/compare_reddit_crypto_tokens.py +++ b/src/adanos/_generated/api/reddit_crypto/compare_reddit_crypto_tokens.py @@ -5,6 +5,7 @@ from ... import errors from ...client import AuthenticatedClient, Client +from ...models.compare_limit_error import CompareLimitError from ...models.crypto_compare_response import CryptoCompareResponse from ...models.error_response import ErrorResponse from ...models.historical_limit_error import HistoricalLimitError @@ -58,7 +59,7 @@ def _parse_response( return response_200 if response.status_code == 400: - response_400 = cast(Any, None) + response_400 = CompareLimitError.from_dict(response.json()) return response_400 if response.status_code == 401: @@ -79,7 +80,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_market_sentiment.py b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_market_sentiment.py index d5b6cce..62fb0fd 100644 --- a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_market_sentiment.py +++ b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_market_sentiment.py @@ -66,7 +66,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token.py b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token.py index 47e91a6..c0dc4a9 100644 --- a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token.py +++ b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token.py @@ -11,6 +11,7 @@ from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError from ...models.invalid_period_error import InvalidPeriodError +from ...models.unsupported_asset_error import UnsupportedAssetError from ...types import UNSET, Response, Unset @@ -69,7 +70,7 @@ def _parse_response( return response_403 if response.status_code == 404: - response_404 = cast(Any, None) + response_404 = UnsupportedAssetError.from_dict(response.json()) return response_404 if response.status_code == 422: @@ -80,7 +81,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token_mentions.py b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token_mentions.py index d692c4d..b6f27d3 100644 --- a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token_mentions.py +++ b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_token_mentions.py @@ -79,7 +79,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_trending.py b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_trending.py index 8c77b8f..3485d6f 100644 --- a/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_trending.py +++ b/src/adanos/_generated/api/reddit_crypto/get_reddit_crypto_trending.py @@ -87,7 +87,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_crypto/search_reddit_crypto.py b/src/adanos/_generated/api/reddit_crypto/search_reddit_crypto.py index 65ae45a..c692d4a 100644 --- a/src/adanos/_generated/api/reddit_crypto/search_reddit_crypto.py +++ b/src/adanos/_generated/api/reddit_crypto/search_reddit_crypto.py @@ -67,7 +67,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/compare_stocks.py b/src/adanos/_generated/api/reddit_stocks/compare_stocks.py index a74702d..5ac0823 100644 --- a/src/adanos/_generated/api/reddit_stocks/compare_stocks.py +++ b/src/adanos/_generated/api/reddit_stocks/compare_stocks.py @@ -5,6 +5,7 @@ from ... import errors from ...client import AuthenticatedClient, Client +from ...models.compare_limit_error import CompareLimitError from ...models.compare_response import CompareResponse from ...models.error_response import ErrorResponse from ...models.historical_limit_error import HistoricalLimitError @@ -58,7 +59,7 @@ def _parse_response( return response_200 if response.status_code == 400: - response_400 = cast(Any, None) + response_400 = CompareLimitError.from_dict(response.json()) return response_400 if response.status_code == 401: @@ -79,7 +80,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_reddit_market_sentiment.py b/src/adanos/_generated/api/reddit_stocks/get_reddit_market_sentiment.py index 68aad4b..725a4cf 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_reddit_market_sentiment.py +++ b/src/adanos/_generated/api/reddit_stocks/get_reddit_market_sentiment.py @@ -66,7 +66,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_stock_explanation.py b/src/adanos/_generated/api/reddit_stocks/get_stock_explanation.py index 5401df2..0ce1ec7 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_stock_explanation.py +++ b/src/adanos/_generated/api/reddit_stocks/get_stock_explanation.py @@ -65,7 +65,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_stock_raw_mentions.py b/src/adanos/_generated/api/reddit_stocks/get_stock_raw_mentions.py index 2e99a51..3519ad8 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_stock_raw_mentions.py +++ b/src/adanos/_generated/api/reddit_stocks/get_stock_raw_mentions.py @@ -79,7 +79,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_stock_sentiment.py b/src/adanos/_generated/api/reddit_stocks/get_stock_sentiment.py index 11a687a..dddf1a4 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_stock_sentiment.py +++ b/src/adanos/_generated/api/reddit_stocks/get_stock_sentiment.py @@ -10,6 +10,7 @@ from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError from ...models.invalid_period_error import InvalidPeriodError +from ...models.unsupported_asset_error import UnsupportedAssetError from ...models.stock_sentiment import StockSentiment from ...types import UNSET, Response, Unset @@ -69,7 +70,7 @@ def _parse_response( return response_403 if response.status_code == 404: - response_404 = cast(Any, None) + response_404 = UnsupportedAssetError.from_dict(response.json()) return response_404 if response.status_code == 422: @@ -80,7 +81,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_trending_countries.py b/src/adanos/_generated/api/reddit_stocks/get_trending_countries.py index e33539c..33f371c 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_trending_countries.py +++ b/src/adanos/_generated/api/reddit_stocks/get_trending_countries.py @@ -87,7 +87,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_trending_sectors.py b/src/adanos/_generated/api/reddit_stocks/get_trending_sectors.py index 4cc549d..ef08221 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_trending_sectors.py +++ b/src/adanos/_generated/api/reddit_stocks/get_trending_sectors.py @@ -87,7 +87,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/get_trending_stocks.py b/src/adanos/_generated/api/reddit_stocks/get_trending_stocks.py index f0f490e..86280c2 100644 --- a/src/adanos/_generated/api/reddit_stocks/get_trending_stocks.py +++ b/src/adanos/_generated/api/reddit_stocks/get_trending_stocks.py @@ -98,7 +98,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/reddit_stocks/search_stocks.py b/src/adanos/_generated/api/reddit_stocks/search_stocks.py index eb4e202..2652a68 100644 --- a/src/adanos/_generated/api/reddit_stocks/search_stocks.py +++ b/src/adanos/_generated/api/reddit_stocks/search_stocks.py @@ -60,7 +60,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/compare_x_stocks.py b/src/adanos/_generated/api/x_twitter_stocks/compare_x_stocks.py index e443e32..4d38fb1 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/compare_x_stocks.py +++ b/src/adanos/_generated/api/x_twitter_stocks/compare_x_stocks.py @@ -5,6 +5,7 @@ from ... import errors from ...client import AuthenticatedClient, Client +from ...models.compare_limit_error import CompareLimitError from ...models.error_response import ErrorResponse from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError @@ -52,7 +53,7 @@ def _parse_response( return response_200 if response.status_code == 400: - response_400 = cast(Any, None) + response_400 = CompareLimitError.from_dict(response.json()) return response_400 if response.status_code == 401: @@ -73,7 +74,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_market_sentiment.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_market_sentiment.py index 4f3054c..412cfa3 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_market_sentiment.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_market_sentiment.py @@ -66,7 +66,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_explanation.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_explanation.py index 6b71d48..ef7d010 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_explanation.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_explanation.py @@ -61,7 +61,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_raw_mentions.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_raw_mentions.py index 6ccf6ee..fa36921 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_raw_mentions.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_raw_mentions.py @@ -76,7 +76,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_sentiment.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_sentiment.py index 26ac982..18f29c9 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_sentiment.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_stock_sentiment.py @@ -10,6 +10,7 @@ from ...models.historical_limit_error import HistoricalLimitError from ...models.http_validation_error import HTTPValidationError from ...models.invalid_period_error import InvalidPeriodError +from ...models.unsupported_asset_error import UnsupportedAssetError from ...models.x_stock_detail_response import XStockDetailResponse from ...types import UNSET, Response, Unset @@ -69,7 +70,7 @@ def _parse_response( return response_403 if response.status_code == 404: - response_404 = cast(Any, None) + response_404 = UnsupportedAssetError.from_dict(response.json()) return response_404 if response.status_code == 422: @@ -80,7 +81,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_countries.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_countries.py index af6152e..a16c37f 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_countries.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_countries.py @@ -82,7 +82,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_sectors.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_sectors.py index 092e020..26c7de1 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_sectors.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_sectors.py @@ -82,7 +82,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_stocks.py b/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_stocks.py index b0b0baf..edee508 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_stocks.py +++ b/src/adanos/_generated/api/x_twitter_stocks/get_x_trending_stocks.py @@ -93,7 +93,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/api/x_twitter_stocks/search_x_stocks.py b/src/adanos/_generated/api/x_twitter_stocks/search_x_stocks.py index 7acaa33..8262935 100644 --- a/src/adanos/_generated/api/x_twitter_stocks/search_x_stocks.py +++ b/src/adanos/_generated/api/x_twitter_stocks/search_x_stocks.py @@ -64,7 +64,7 @@ def _parse_response_422(data: object) -> HTTPValidationError | InvalidPeriodErro raise TypeError() detail = data.get("detail") error = str(detail.get("error", "")).lower().replace(" ", "_") if isinstance(detail, dict) else "" - if error != "invalid_period": + if error not in {"invalid_period", "data_unavailable"}: raise TypeError() response_422_type_0 = InvalidPeriodError.from_dict(data) diff --git a/src/adanos/_generated/models/__init__.py b/src/adanos/_generated/models/__init__.py index 7fa6bd0..876ec2d 100644 --- a/src/adanos/_generated/models/__init__.py +++ b/src/adanos/_generated/models/__init__.py @@ -1,5 +1,7 @@ """Contains all the data models used in inputs/outputs""" +from .compare_limit_error import CompareLimitError +from .compare_limit_error_detail import CompareLimitErrorDetail from .compare_response import CompareResponse from .compare_stock_item import CompareStockItem from .compare_stock_item_trend_type_0 import CompareStockItemTrendType0 @@ -67,6 +69,7 @@ from .polymarket_market_sentiment_driver import PolymarketMarketSentimentDriver from .polymarket_market_sentiment_response import PolymarketMarketSentimentResponse from .polymarket_market_sentiment_response_trend_type_0 import PolymarketMarketSentimentResponseTrendType0 +from .polymarket_pulse_evidence import PolymarketPulseEvidence from .polymarket_raw_mention_item import PolymarketRawMentionItem from .polymarket_raw_mention_item_sentiment_label_type_0 import PolymarketRawMentionItemSentimentLabelType0 from .polymarket_raw_mentions_response import PolymarketRawMentionsResponse @@ -78,6 +81,8 @@ from .polymarket_stats_response import PolymarketStatsResponse from .polymarket_stock_detail_response import PolymarketStockDetailResponse from .polymarket_stock_detail_response_trend_type_0 import PolymarketStockDetailResponseTrendType0 +from .polymarket_ticker_pulse import PolymarketTickerPulse +from .polymarket_ticker_pulse_mood import PolymarketTickerPulseMood from .polymarket_top_mention import PolymarketTopMention from .polymarket_trending_country import PolymarketTrendingCountry from .polymarket_trending_country_trend import PolymarketTrendingCountryTrend @@ -114,6 +119,8 @@ from .trending_sector_trend import TrendingSectorTrend from .trending_stock import TrendingStock from .trending_stock_trend import TrendingStockTrend +from .unsupported_asset_error import UnsupportedAssetError +from .unsupported_asset_error_detail import UnsupportedAssetErrorDetail from .validation_error import ValidationError from .validation_error_context import ValidationErrorContext from .x_compare_response import XCompareResponse @@ -141,8 +148,11 @@ from .x_trending_sector import XTrendingSector from .x_trending_sector_trend import XTrendingSectorTrend from .x_trending_stock import XTrendingStock +from .x_trending_stock_trend import XTrendingStockTrend __all__ = ( + "CompareLimitError", + "CompareLimitErrorDetail", "CompareResponse", "CompareStockItem", "CompareStockItemTrendType0", @@ -210,6 +220,7 @@ "PolymarketMarketSentimentDriver", "PolymarketMarketSentimentResponse", "PolymarketMarketSentimentResponseTrendType0", + "PolymarketPulseEvidence", "PolymarketRawMentionItem", "PolymarketRawMentionItemSentimentLabelType0", "PolymarketRawMentionsResponse", @@ -221,6 +232,8 @@ "PolymarketStatsResponse", "PolymarketStockDetailResponse", "PolymarketStockDetailResponseTrendType0", + "PolymarketTickerPulse", + "PolymarketTickerPulseMood", "PolymarketTopMention", "PolymarketTrendingCountry", "PolymarketTrendingCountryTrend", @@ -257,6 +270,8 @@ "TrendingSectorTrend", "TrendingStock", "TrendingStockTrend", + "UnsupportedAssetError", + "UnsupportedAssetErrorDetail", "ValidationError", "ValidationErrorContext", "XCompareResponse", @@ -284,4 +299,5 @@ "XTrendingSector", "XTrendingSectorTrend", "XTrendingStock", + "XTrendingStockTrend", ) diff --git a/src/adanos/_generated/models/compare_limit_error.py b/src/adanos/_generated/models/compare_limit_error.py new file mode 100644 index 0000000..dcba1c9 --- /dev/null +++ b/src/adanos/_generated/models/compare_limit_error.py @@ -0,0 +1,68 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.compare_limit_error_detail import CompareLimitErrorDetail + + +T = TypeVar("T", bound="CompareLimitError") + + +@_attrs_define +class CompareLimitError: + """Error response for compare item-count violations (HTTP 400). + + Attributes: + detail (CompareLimitErrorDetail): Structured error detail for compare item-count violations. + """ + + detail: CompareLimitErrorDetail + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + detail = self.detail.to_dict() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "detail": detail, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.compare_limit_error_detail import CompareLimitErrorDetail + + d = dict(src_dict) + detail = CompareLimitErrorDetail.from_dict(d.pop("detail")) + + compare_limit_error = cls( + detail=detail, + ) + + compare_limit_error.additional_properties = d + return compare_limit_error + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/adanos/_generated/models/compare_limit_error_detail.py b/src/adanos/_generated/models/compare_limit_error_detail.py new file mode 100644 index 0000000..cc54824 --- /dev/null +++ b/src/adanos/_generated/models/compare_limit_error_detail.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="CompareLimitErrorDetail") + + +@_attrs_define +class CompareLimitErrorDetail: + """Structured error detail for compare item-count violations. + + Attributes: + error (str): Machine-readable error code + message (str): Human-readable error message + max_items (int): Maximum accepted compare items + item_name (str): Compared item type, such as ticker or symbol + """ + + error: str + message: str + max_items: int + item_name: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + error = self.error + + message = self.message + + max_items = self.max_items + + item_name = self.item_name + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "error": error, + "message": message, + "max_items": max_items, + "item_name": item_name, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + error = d.pop("error") + + message = d.pop("message") + + max_items = d.pop("max_items") + + item_name = d.pop("item_name") + + compare_limit_error_detail = cls( + error=error, + message=message, + max_items=max_items, + item_name=item_name, + ) + + compare_limit_error_detail.additional_properties = d + return compare_limit_error_detail + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/adanos/_generated/models/crypto_daily_trend_item.py b/src/adanos/_generated/models/crypto_daily_trend_item.py index 174e842..d1b4c65 100644 --- a/src/adanos/_generated/models/crypto_daily_trend_item.py +++ b/src/adanos/_generated/models/crypto_daily_trend_item.py @@ -22,12 +22,16 @@ class CryptoDailyTrendItem: mentions (int): Explicit mention count for the day sentiment_score (float | None | Unset): Average sentiment score for the day buzz_score (float | None | Unset): Daily buzz score + bullish_pct (int | None | Unset): Bullish mention percentage for the day + bearish_pct (int | None | Unset): Bearish mention percentage for the day """ date: datetime.date mentions: int sentiment_score: float | None | Unset = UNSET buzz_score: float | None | Unset = UNSET + bullish_pct: int | None | Unset = UNSET + bearish_pct: int | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -47,6 +51,10 @@ def to_dict(self) -> dict[str, Any]: else: buzz_score = self.buzz_score + bullish_pct = self.bullish_pct + + bearish_pct = self.bearish_pct + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -59,6 +67,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["sentiment_score"] = sentiment_score if buzz_score is not UNSET: field_dict["buzz_score"] = buzz_score + if bullish_pct is not UNSET: + field_dict["bullish_pct"] = bullish_pct + if bearish_pct is not UNSET: + field_dict["bearish_pct"] = bearish_pct return field_dict @@ -87,11 +99,17 @@ def _parse_buzz_score(data: object) -> float | None | Unset: buzz_score = _parse_buzz_score(d.pop("buzz_score", UNSET)) + bullish_pct = cast(int | None | Unset, d.pop("bullish_pct", UNSET)) + + bearish_pct = cast(int | None | Unset, d.pop("bearish_pct", UNSET)) + crypto_daily_trend_item = cls( date=date, mentions=mentions, sentiment_score=sentiment_score, buzz_score=buzz_score, + bullish_pct=bullish_pct, + bearish_pct=bearish_pct, ) crypto_daily_trend_item.additional_properties = d diff --git a/src/adanos/_generated/models/crypto_token_sentiment_daily_trend_type_0_item.py b/src/adanos/_generated/models/crypto_token_sentiment_daily_trend_type_0_item.py index e532b3f..fe91b85 100644 --- a/src/adanos/_generated/models/crypto_token_sentiment_daily_trend_type_0_item.py +++ b/src/adanos/_generated/models/crypto_token_sentiment_daily_trend_type_0_item.py @@ -19,6 +19,8 @@ class CryptoTokenSentimentDailyTrendType0Item: mentions: int sentiment_score: float | None | Unset = UNSET buzz_score: float | None | Unset = UNSET + bullish_pct: int | None | Unset = UNSET + bearish_pct: int | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -29,6 +31,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["sentiment_score"] = self.sentiment_score if self.buzz_score is not UNSET: field_dict["buzz_score"] = self.buzz_score + if self.bullish_pct is not UNSET: + field_dict["bullish_pct"] = self.bullish_pct + if self.bearish_pct is not UNSET: + field_dict["bearish_pct"] = self.bearish_pct return field_dict @classmethod @@ -47,6 +53,8 @@ def _parse_float(data: object) -> float | None | Unset: mentions=d.pop("mentions"), sentiment_score=_parse_float(d.pop("sentiment_score", UNSET)), buzz_score=_parse_float(d.pop("buzz_score", UNSET)), + bullish_pct=cast(int | None | Unset, d.pop("bullish_pct", UNSET)), + bearish_pct=cast(int | None | Unset, d.pop("bearish_pct", UNSET)), ) item.additional_properties = d return item diff --git a/src/adanos/_generated/models/daily_trend_item.py b/src/adanos/_generated/models/daily_trend_item.py index 0a8c384..4cbf327 100644 --- a/src/adanos/_generated/models/daily_trend_item.py +++ b/src/adanos/_generated/models/daily_trend_item.py @@ -20,12 +20,16 @@ class DailyTrendItem: mentions (int): Number of mentions on this date sentiment_score (float | None | Unset): Canonical average sentiment for this date buzz_score (float | None | Unset): Buzz score for this date (0-100) + bullish_pct (int | None | Unset): Bullish mention percentage for this date + bearish_pct (int | None | Unset): Bearish mention percentage for this date """ date: str mentions: int sentiment_score: float | None | Unset = UNSET buzz_score: float | None | Unset = UNSET + bullish_pct: int | None | Unset = UNSET + bearish_pct: int | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -45,6 +49,10 @@ def to_dict(self) -> dict[str, Any]: else: buzz_score = self.buzz_score + bullish_pct = self.bullish_pct + + bearish_pct = self.bearish_pct + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -57,6 +65,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["sentiment_score"] = sentiment_score if buzz_score is not UNSET: field_dict["buzz_score"] = buzz_score + if bullish_pct is not UNSET: + field_dict["bullish_pct"] = bullish_pct + if bearish_pct is not UNSET: + field_dict["bearish_pct"] = bearish_pct return field_dict @@ -85,11 +97,17 @@ def _parse_buzz_score(data: object) -> float | None | Unset: buzz_score = _parse_buzz_score(d.pop("buzz_score", UNSET)) + bullish_pct = cast(int | None | Unset, d.pop("bullish_pct", UNSET)) + + bearish_pct = cast(int | None | Unset, d.pop("bearish_pct", UNSET)) + daily_trend_item = cls( date=date, mentions=mentions, sentiment_score=sentiment_score, buzz_score=buzz_score, + bullish_pct=bullish_pct, + bearish_pct=bearish_pct, ) daily_trend_item.additional_properties = d diff --git a/src/adanos/_generated/models/invalid_period_error_detail.py b/src/adanos/_generated/models/invalid_period_error_detail.py index 74b04c8..524e8fd 100644 --- a/src/adanos/_generated/models/invalid_period_error_detail.py +++ b/src/adanos/_generated/models/invalid_period_error_detail.py @@ -19,15 +19,29 @@ class InvalidPeriodErrorDetail: Attributes: error (str): Error type identifier message (str): Human-readable error message + field (None | str | Unset): Invalid query parameter name + value (int | None | str | Unset): Invalid query parameter value + today (datetime.date | None | Unset): Current UTC date used for validation period_from (datetime.date | None | Unset): Resolved inclusive UTC start date + period_to (datetime.date | None | Unset): Resolved inclusive UTC end date available_since (datetime.date | None | Unset): Earliest public data date for the platform + retention_from (datetime.date | None | Unset): Earliest date retained for the endpoint + requested_days (int | None | Unset): Number of days requested + max_days (int | None | Unset): Maximum days accepted by the endpoint platform (None | str | Unset): Platform identifier """ error: str message: str + field: None | str | Unset = UNSET + value: int | None | str | Unset = UNSET + today: datetime.date | None | Unset = UNSET period_from: datetime.date | None | Unset = UNSET + period_to: datetime.date | None | Unset = UNSET available_since: datetime.date | None | Unset = UNSET + retention_from: datetime.date | None | Unset = UNSET + requested_days: int | None | Unset = UNSET + max_days: int | None | Unset = UNSET platform: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -36,6 +50,26 @@ def to_dict(self) -> dict[str, Any]: message = self.message + field: None | str | Unset + if isinstance(self.field, Unset): + field = UNSET + else: + field = self.field + + value: int | None | str | Unset + if isinstance(self.value, Unset): + value = UNSET + else: + value = self.value + + today: None | str | Unset + if isinstance(self.today, Unset): + today = UNSET + elif isinstance(self.today, datetime.date): + today = self.today.isoformat() + else: + today = self.today + period_from: None | str | Unset if isinstance(self.period_from, Unset): period_from = UNSET @@ -44,6 +78,14 @@ def to_dict(self) -> dict[str, Any]: else: period_from = self.period_from + period_to: None | str | Unset + if isinstance(self.period_to, Unset): + period_to = UNSET + elif isinstance(self.period_to, datetime.date): + period_to = self.period_to.isoformat() + else: + period_to = self.period_to + available_since: None | str | Unset if isinstance(self.available_since, Unset): available_since = UNSET @@ -52,6 +94,26 @@ def to_dict(self) -> dict[str, Any]: else: available_since = self.available_since + retention_from: None | str | Unset + if isinstance(self.retention_from, Unset): + retention_from = UNSET + elif isinstance(self.retention_from, datetime.date): + retention_from = self.retention_from.isoformat() + else: + retention_from = self.retention_from + + requested_days: int | None | Unset + if isinstance(self.requested_days, Unset): + requested_days = UNSET + else: + requested_days = self.requested_days + + max_days: int | None | Unset + if isinstance(self.max_days, Unset): + max_days = UNSET + else: + max_days = self.max_days + platform: None | str | Unset if isinstance(self.platform, Unset): platform = UNSET @@ -66,10 +128,24 @@ def to_dict(self) -> dict[str, Any]: "message": message, } ) + if field is not UNSET: + field_dict["field"] = field + if value is not UNSET: + field_dict["value"] = value + if today is not UNSET: + field_dict["today"] = today if period_from is not UNSET: field_dict["period_from"] = period_from + if period_to is not UNSET: + field_dict["period_to"] = period_to if available_since is not UNSET: field_dict["available_since"] = available_since + if retention_from is not UNSET: + field_dict["retention_from"] = retention_from + if requested_days is not UNSET: + field_dict["requested_days"] = requested_days + if max_days is not UNSET: + field_dict["max_days"] = max_days if platform is not UNSET: field_dict["platform"] = platform @@ -82,6 +158,41 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: message = d.pop("message") + def _parse_field(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + field = _parse_field(d.pop("field", UNSET)) + + def _parse_value(data: object) -> int | None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | str | Unset, data) + + value = _parse_value(d.pop("value", UNSET)) + + def _parse_today(data: object) -> datetime.date | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + today_type_0 = datetime.date.fromisoformat(data) + + return today_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + today = _parse_today(d.pop("today", UNSET)) + def _parse_period_from(data: object) -> datetime.date | None | Unset: if data is None: return data @@ -99,6 +210,23 @@ def _parse_period_from(data: object) -> datetime.date | None | Unset: period_from = _parse_period_from(d.pop("period_from", UNSET)) + def _parse_period_to(data: object) -> datetime.date | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + period_to_type_0 = datetime.date.fromisoformat(data) + + return period_to_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + period_to = _parse_period_to(d.pop("period_to", UNSET)) + def _parse_available_since(data: object) -> datetime.date | None | Unset: if data is None: return data @@ -116,6 +244,41 @@ def _parse_available_since(data: object) -> datetime.date | None | Unset: available_since = _parse_available_since(d.pop("available_since", UNSET)) + def _parse_retention_from(data: object) -> datetime.date | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + retention_from_type_0 = datetime.date.fromisoformat(data) + + return retention_from_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + retention_from = _parse_retention_from(d.pop("retention_from", UNSET)) + + def _parse_requested_days(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + requested_days = _parse_requested_days(d.pop("requested_days", UNSET)) + + def _parse_max_days(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + max_days = _parse_max_days(d.pop("max_days", UNSET)) + def _parse_platform(data: object) -> None | str | Unset: if data is None: return data @@ -128,8 +291,15 @@ def _parse_platform(data: object) -> None | str | Unset: invalid_period_error_detail = cls( error=error, message=message, + field=field, + value=value, + today=today, period_from=period_from, + period_to=period_to, available_since=available_since, + retention_from=retention_from, + requested_days=requested_days, + max_days=max_days, platform=platform, ) diff --git a/src/adanos/_generated/models/polymarket_daily_trend_item.py b/src/adanos/_generated/models/polymarket_daily_trend_item.py index 1a20519..290f7f7 100644 --- a/src/adanos/_generated/models/polymarket_daily_trend_item.py +++ b/src/adanos/_generated/models/polymarket_daily_trend_item.py @@ -20,12 +20,16 @@ class PolymarketDailyTrendItem: trade_count (int): Trade count on this date sentiment_score (float | None | Unset): Canonical implied sentiment on this date buzz_score (float | None | Unset): Buzz score on this date + bullish_pct (int | None | Unset): Bullish market-direction percentage for this date + bearish_pct (int | None | Unset): Bearish market-direction percentage for this date """ date: str trade_count: int sentiment_score: float | None | Unset = UNSET buzz_score: float | None | Unset = UNSET + bullish_pct: int | None | Unset = UNSET + bearish_pct: int | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -45,6 +49,10 @@ def to_dict(self) -> dict[str, Any]: else: buzz_score = self.buzz_score + bullish_pct = self.bullish_pct + + bearish_pct = self.bearish_pct + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -57,6 +65,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["sentiment_score"] = sentiment_score if buzz_score is not UNSET: field_dict["buzz_score"] = buzz_score + if bullish_pct is not UNSET: + field_dict["bullish_pct"] = bullish_pct + if bearish_pct is not UNSET: + field_dict["bearish_pct"] = bearish_pct return field_dict @@ -85,11 +97,17 @@ def _parse_buzz_score(data: object) -> float | None | Unset: buzz_score = _parse_buzz_score(d.pop("buzz_score", UNSET)) + bullish_pct = cast(int | None | Unset, d.pop("bullish_pct", UNSET)) + + bearish_pct = cast(int | None | Unset, d.pop("bearish_pct", UNSET)) + polymarket_daily_trend_item = cls( date=date, trade_count=trade_count, sentiment_score=sentiment_score, buzz_score=buzz_score, + bullish_pct=bullish_pct, + bearish_pct=bearish_pct, ) polymarket_daily_trend_item.additional_properties = d diff --git a/src/adanos/_generated/models/polymarket_market_sentiment_response.py b/src/adanos/_generated/models/polymarket_market_sentiment_response.py index 3c7c434..241f48e 100644 --- a/src/adanos/_generated/models/polymarket_market_sentiment_response.py +++ b/src/adanos/_generated/models/polymarket_market_sentiment_response.py @@ -21,36 +21,41 @@ class PolymarketMarketSentimentResponse: """Service-level Polymarket market sentiment across all tracked stocks. Attributes: - buzz_score (float): Service-wide Polymarket heat score relative to the service's trailing 90-day baseline. - Around 50 = normal activity, higher values = hotter-than-usual Polymarket activity. + buzz_score (float | None): Service-wide Polymarket heat score relative to the service's trailing 90-day + baseline. Around 50 = normal activity, higher values = hotter-than-usual Polymarket activity. trade_count (int): Service-wide trade count in the selected period - market_count (int): Best-effort sum of per-ticker distinct markets active in the selected period; not an exact - global condition-id union, and longer windows use per-ticker daily-rollup breadth fallback - current_market_count (int): Sum of ticker-level currently active markets in the latest UTC-day snapshot; use - this for live-only market breadth - unique_traders (int): Best-effort service-wide unique trader signal in the selected period + market_count (int): Sum of ticker-level catalog lifetime-overlap market counts in the selected UTC window; not a + cross-ticker global condition-id union + current_market_count (int): Sum of ticker-level currently open markets in the latest UTC-day snapshot; use this + for live-only market breadth + unique_traders (int | None | Unset): Exact service-wide observed participant/proxy-wallet union in the selected + period; null when retained wallet-level trades do not fully cover the requested window total_liquidity (float): Windowed aggregated liquidity signal in USD over the selected period active_tickers (int): Number of tickers with market activity in the selected period - positive_count (int): Outcome-aware bullish market count - negative_count (int): Outcome-aware bearish market count - neutral_count (int): Markets with neutral or unclassified outcome direction + positive_count (int): Deprecated. Outcome-aware bullish market count retained for v1 compatibility; prefer + bullish_pct with trade_count and market_count for public analysis. + negative_count (int): Deprecated. Outcome-aware bearish market count retained for v1 compatibility; prefer + bearish_pct with trade_count and market_count for public analysis. + neutral_count (int): Deprecated. Outcome-aware neutral/unclassified market count retained for v1 compatibility; + prefer bullish_pct, bearish_pct, trade_count and market_count for public analysis. bullish_pct (int): Outcome-aware bullish market percentage bearish_pct (int): Outcome-aware bearish market percentage - trend (None | PolymarketMarketSentimentResponseTrendType0 | Unset): Service-level Polymarket flow trend over - current 3 UTC days vs previous 3 UTC days using trades, volume, market breadth, traders, and liquidity - sentiment_score (float | None | Unset): Service-wide weighted implied sentiment score + trend (None | PolymarketMarketSentimentResponseTrendType0 | Unset): Flow momentum over the current 3 UTC days vs + previous 3 UTC days using trades, volume, market breadth and liquidity; not price movement. Null when the + selected window has no measurable Polymarket heat. For `from`/`to`, anchors at `to` (or now when `to` is today). + sentiment_score (float | None | Unset): Service-wide weighted orderbook-aware implied sentiment score trend_history (list[float] | Unset): Daily service-wide buzz scores (oldest→newest) using the same relative - baseline calibration. Length = max(effective_days, 7), where effective_days reflects any platform availability - clamp. + baseline calibration. Length = max(requested_days, 7) for successful requests; windows before platform + availability return HTTP 422. drivers (list[PolymarketMarketSentimentDriver] | Unset): Top assets by current buzz_score driving the service- level reading """ - buzz_score: float + buzz_score: float | None trade_count: int market_count: int current_market_count: int - unique_traders: int + unique_traders: int | None | Unset total_liquidity: float active_tickers: int positive_count: int @@ -65,6 +70,7 @@ class PolymarketMarketSentimentResponse: additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + buzz_score: float | None buzz_score = self.buzz_score trade_count = self.trade_count @@ -73,8 +79,6 @@ def to_dict(self) -> dict[str, Any]: current_market_count = self.current_market_count - unique_traders = self.unique_traders - total_liquidity = self.total_liquidity active_tickers = self.active_tickers @@ -97,6 +101,12 @@ def to_dict(self) -> dict[str, Any]: else: trend = self.trend + unique_traders: int | None | Unset + if isinstance(self.unique_traders, Unset): + unique_traders = UNSET + else: + unique_traders = self.unique_traders + sentiment_score: float | None | Unset if isinstance(self.sentiment_score, Unset): sentiment_score = UNSET @@ -122,7 +132,6 @@ def to_dict(self) -> dict[str, Any]: "trade_count": trade_count, "market_count": market_count, "current_market_count": current_market_count, - "unique_traders": unique_traders, "total_liquidity": total_liquidity, "active_tickers": active_tickers, "positive_count": positive_count, @@ -134,6 +143,8 @@ def to_dict(self) -> dict[str, Any]: ) if trend is not UNSET: field_dict["trend"] = trend + if unique_traders is not UNSET: + field_dict["unique_traders"] = unique_traders if sentiment_score is not UNSET: field_dict["sentiment_score"] = sentiment_score if trend_history is not UNSET: @@ -148,7 +159,13 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.polymarket_market_sentiment_driver import PolymarketMarketSentimentDriver d = dict(src_dict) - buzz_score = d.pop("buzz_score") + + def _parse_buzz_score(data: object) -> float | None: + if data is None: + return data + return cast(float | None, data) + + buzz_score = _parse_buzz_score(d.pop("buzz_score")) trade_count = d.pop("trade_count") @@ -156,8 +173,6 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: current_market_count = d.pop("current_market_count") - unique_traders = d.pop("unique_traders") - total_liquidity = d.pop("total_liquidity") active_tickers = d.pop("active_tickers") @@ -189,6 +204,15 @@ def _parse_trend(data: object) -> None | PolymarketMarketSentimentResponseTrendT trend = _parse_trend(d.pop("trend", UNSET)) + def _parse_unique_traders(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + unique_traders = _parse_unique_traders(d.pop("unique_traders", UNSET)) + def _parse_sentiment_score(data: object) -> float | None | Unset: if data is None: return data @@ -214,7 +238,6 @@ def _parse_sentiment_score(data: object) -> float | None | Unset: trade_count=trade_count, market_count=market_count, current_market_count=current_market_count, - unique_traders=unique_traders, total_liquidity=total_liquidity, active_tickers=active_tickers, positive_count=positive_count, @@ -223,6 +246,7 @@ def _parse_sentiment_score(data: object) -> float | None | Unset: bullish_pct=bullish_pct, bearish_pct=bearish_pct, trend=trend, + unique_traders=unique_traders, sentiment_score=sentiment_score, trend_history=trend_history, drivers=drivers, diff --git a/src/adanos/_generated/models/polymarket_pulse_evidence.py b/src/adanos/_generated/models/polymarket_pulse_evidence.py new file mode 100644 index 0000000..9be46ff --- /dev/null +++ b/src/adanos/_generated/models/polymarket_pulse_evidence.py @@ -0,0 +1,169 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="PolymarketPulseEvidence") + + +@_attrs_define +class PolymarketPulseEvidence: + """Compact data-quality evidence for the ticker-level Polymarket pulse. + + Attributes: + directional_coverage (float | None | Unset): Share of current open snapshot markets with outcome-aware + directional evidence + traded_market_pct (float | None | Unset): Share of current open snapshot markets with trades in the latest UTC + day + zero_trade_market_pct (float | None | Unset): Share of current open snapshot markets without trades in the + latest UTC day + avg_spread (float | None | Unset): Average YES-token spread across current open snapshot markets with bid/ask + spread evidence + snapshot_at (datetime.datetime | None | Unset): Latest stored snapshot timestamp used by the pulse read model + """ + + directional_coverage: float | None | Unset = UNSET + traded_market_pct: float | None | Unset = UNSET + zero_trade_market_pct: float | None | Unset = UNSET + avg_spread: float | None | Unset = UNSET + snapshot_at: datetime.datetime | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + directional_coverage: float | None | Unset + if isinstance(self.directional_coverage, Unset): + directional_coverage = UNSET + else: + directional_coverage = self.directional_coverage + + traded_market_pct: float | None | Unset + if isinstance(self.traded_market_pct, Unset): + traded_market_pct = UNSET + else: + traded_market_pct = self.traded_market_pct + + zero_trade_market_pct: float | None | Unset + if isinstance(self.zero_trade_market_pct, Unset): + zero_trade_market_pct = UNSET + else: + zero_trade_market_pct = self.zero_trade_market_pct + + avg_spread: float | None | Unset + if isinstance(self.avg_spread, Unset): + avg_spread = UNSET + else: + avg_spread = self.avg_spread + + snapshot_at: None | str | Unset + if isinstance(self.snapshot_at, Unset): + snapshot_at = UNSET + elif isinstance(self.snapshot_at, datetime.datetime): + snapshot_at = self.snapshot_at.isoformat() + else: + snapshot_at = self.snapshot_at + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if directional_coverage is not UNSET: + field_dict["directional_coverage"] = directional_coverage + if traded_market_pct is not UNSET: + field_dict["traded_market_pct"] = traded_market_pct + if zero_trade_market_pct is not UNSET: + field_dict["zero_trade_market_pct"] = zero_trade_market_pct + if avg_spread is not UNSET: + field_dict["avg_spread"] = avg_spread + if snapshot_at is not UNSET: + field_dict["snapshot_at"] = snapshot_at + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + + def _parse_directional_coverage(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + directional_coverage = _parse_directional_coverage(d.pop("directional_coverage", UNSET)) + + def _parse_traded_market_pct(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + traded_market_pct = _parse_traded_market_pct(d.pop("traded_market_pct", UNSET)) + + def _parse_zero_trade_market_pct(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + zero_trade_market_pct = _parse_zero_trade_market_pct(d.pop("zero_trade_market_pct", UNSET)) + + def _parse_avg_spread(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + avg_spread = _parse_avg_spread(d.pop("avg_spread", UNSET)) + + def _parse_snapshot_at(data: object) -> datetime.datetime | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + snapshot_at_type_0 = datetime.datetime.fromisoformat(data) + + return snapshot_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None | Unset, data) + + snapshot_at = _parse_snapshot_at(d.pop("snapshot_at", UNSET)) + + polymarket_pulse_evidence = cls( + directional_coverage=directional_coverage, + traded_market_pct=traded_market_pct, + zero_trade_market_pct=zero_trade_market_pct, + avg_spread=avg_spread, + snapshot_at=snapshot_at, + ) + + polymarket_pulse_evidence.additional_properties = d + return polymarket_pulse_evidence + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/adanos/_generated/models/polymarket_stock_detail_response.py b/src/adanos/_generated/models/polymarket_stock_detail_response.py index faf123b..c258cc9 100644 --- a/src/adanos/_generated/models/polymarket_stock_detail_response.py +++ b/src/adanos/_generated/models/polymarket_stock_detail_response.py @@ -6,13 +6,12 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field -from ..models.polymarket_stock_detail_response_trend_type_0 import ( - PolymarketStockDetailResponseTrendType0, -) +from ..models.polymarket_stock_detail_response_trend_type_0 import PolymarketStockDetailResponseTrendType0 from ..types import UNSET, Unset if TYPE_CHECKING: from ..models.polymarket_daily_trend_item import PolymarketDailyTrendItem + from ..models.polymarket_ticker_pulse import PolymarketTickerPulse from ..models.polymarket_top_mention import PolymarketTopMention @@ -25,24 +24,48 @@ class PolymarketStockDetailResponse: Attributes: ticker (str): Stock ticker symbol - found (bool): Whether data for ticker exists + found (bool): Legacy v1 data-availability flag. `true` means this service has qualifying data for this + asset/window. `false` means the asset is supported, but this service has no qualifying data for the requested + window. Planned for removal in v2. company_name (None | str | Unset): Company name from ticker_reference buzz_score (float | None | Unset): Buzz score (0-100) - trend (None | PolymarketStockDetailResponseTrendType0 | Unset): UTC-day activity trend vs previous UTC day + trend (None | PolymarketStockDetailResponseTrendType0 | Unset): Flow momentum over the current 3 UTC days vs + previous 3 UTC days using trades, volume, market breadth and liquidity; not price movement. For `from`/`to`, + anchors at `to` (or now when `to` is today). period_days (int | None | Unset): Analysis period in days trade_count (int | None | Unset): Trade count in period - market_count (int | None | Unset): Number of active markets for ticker - current_market_count (int | None | Unset): Number of currently active markets in the latest UTC-day snapshot - unique_traders (int | None | Unset): Sum of per-market day unique trader counters (can overcount across markets) - sentiment_score (float | None | Unset): Implied sentiment - positive_count (int | None | Unset): Markets with YES > 0.5 - negative_count (int | None | Unset): Markets with YES < 0.5 - neutral_count (int | None | Unset): Markets with YES ~= 0.5 - bullish_pct (int | None | Unset): Bullish market share - bearish_pct (int | None | Unset): Bearish market share - total_liquidity (float | None | Unset): Total liquidity (USD) - daily_trend (list[PolymarketDailyTrendItem] | None | Unset): Daily trend data (completed days) - top_mentions (list[PolymarketTopMention] | None | Unset): Top active markets by liquidity + market_count (int | None | Unset): Distinct markets that existed for ticker within the selected UTC window, + counted by market-catalog lifetime overlap + current_market_count (int | None | Unset): Number of currently open markets in the latest UTC-day snapshot for + ticker; use this for live-only market breadth + unique_traders (int | None | Unset): Exact distinct union of observed proxy and explicit maker wallet hashes for + the delivered scope and UTC window; null when retained wallet-level trades do not fully cover the window; not a + complete market-wide participant census + sentiment_score (float | None | Unset): Orderbook-aware implied sentiment; null when no directional sentiment + evidence exists in the selected period + positive_count (int | None | Unset): Deprecated. Outcome-aware bullish market count retained for v1 + compatibility; prefer bullish_pct with trade_count and market_count for public analysis. + negative_count (int | None | Unset): Deprecated. Outcome-aware bearish market count retained for v1 + compatibility; prefer bearish_pct with trade_count and market_count for public analysis. + neutral_count (int | None | Unset): Deprecated. Outcome-aware neutral/unclassified market count retained for v1 + compatibility; prefer bullish_pct, bearish_pct, trade_count and market_count for public analysis. + bullish_pct (int | None | Unset): Outcome-aware bullish market percentage + bearish_pct (int | None | Unset): Outcome-aware bearish market percentage + total_liquidity (float | None | Unset): Windowed aggregated liquidity signal in USD over the selected period; + not a current snapshot + daily_trend (list[PolymarketDailyTrendItem] | None | Unset): Daily activity breakdown for the selected period + top_mentions (list[PolymarketTopMention] | None | Unset): Top markets with an active/open snapshot during the + retained snapshot portion of the selected UTC-day period for this ticker (including the current UTC day so far), + capped at 10 and sorted as representative sentiment evidence: outcome-aware directional markets first, opposing + signals kept visible when present, then trade count, with non-open markets de-prioritized and 24h volume and + liquidity as tie-breakers. For windows longer than raw snapshot retention, ticker analytics still use + `polymarket_daily_stats`, but this representative snapshot list is limited to retained + `polymarket_market_snapshots`. Item prices and liquidity come from the selected in-period snapshot, not + necessarily the current market state. `active` indicates whether the market is currently open, so historical in- + period evidence can now have a non-open current state. `market_status` gives the compact current state. + pulse (None | PolymarketTickerPulse | Unset): Compact current Polymarket interpretation built from locally + stored latest snapshot evidence. Does not duplicate top-level aggregate fields; concrete market evidence remains + in `top_mentions`. """ ticker: str @@ -64,9 +87,12 @@ class PolymarketStockDetailResponse: total_liquidity: float | None | Unset = UNSET daily_trend: list[PolymarketDailyTrendItem] | None | Unset = UNSET top_mentions: list[PolymarketTopMention] | None | Unset = UNSET + pulse: None | PolymarketTickerPulse | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + from ..models.polymarket_ticker_pulse import PolymarketTickerPulse + ticker = self.ticker found = self.found @@ -187,6 +213,14 @@ def to_dict(self) -> dict[str, Any]: else: top_mentions = self.top_mentions + pulse: dict[str, Any] | None | Unset + if isinstance(self.pulse, Unset): + pulse = UNSET + elif isinstance(self.pulse, PolymarketTickerPulse): + pulse = self.pulse.to_dict() + else: + pulse = self.pulse + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -229,12 +263,15 @@ def to_dict(self) -> dict[str, Any]: field_dict["daily_trend"] = daily_trend if top_mentions is not UNSET: field_dict["top_mentions"] = top_mentions + if pulse is not UNSET: + field_dict["pulse"] = pulse return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.polymarket_daily_trend_item import PolymarketDailyTrendItem + from ..models.polymarket_ticker_pulse import PolymarketTickerPulse from ..models.polymarket_top_mention import PolymarketTopMention d = dict(src_dict) @@ -260,9 +297,7 @@ def _parse_buzz_score(data: object) -> float | None | Unset: buzz_score = _parse_buzz_score(d.pop("buzz_score", UNSET)) - def _parse_trend( - data: object, - ) -> None | PolymarketStockDetailResponseTrendType0 | Unset: + def _parse_trend(data: object) -> None | PolymarketStockDetailResponseTrendType0 | Unset: if data is None: return data if isinstance(data, Unset): @@ -387,9 +422,7 @@ def _parse_total_liquidity(data: object) -> float | None | Unset: total_liquidity = _parse_total_liquidity(d.pop("total_liquidity", UNSET)) - def _parse_daily_trend( - data: object, - ) -> list[PolymarketDailyTrendItem] | None | Unset: + def _parse_daily_trend(data: object) -> list[PolymarketDailyTrendItem] | None | Unset: if data is None: return data if isinstance(data, Unset): @@ -400,9 +433,7 @@ def _parse_daily_trend( daily_trend_type_0 = [] _daily_trend_type_0 = data for daily_trend_type_0_item_data in _daily_trend_type_0: - daily_trend_type_0_item = PolymarketDailyTrendItem.from_dict( - daily_trend_type_0_item_data - ) + daily_trend_type_0_item = PolymarketDailyTrendItem.from_dict(daily_trend_type_0_item_data) daily_trend_type_0.append(daily_trend_type_0_item) @@ -413,9 +444,7 @@ def _parse_daily_trend( daily_trend = _parse_daily_trend(d.pop("daily_trend", UNSET)) - def _parse_top_mentions( - data: object, - ) -> list[PolymarketTopMention] | None | Unset: + def _parse_top_mentions(data: object) -> list[PolymarketTopMention] | None | Unset: if data is None: return data if isinstance(data, Unset): @@ -426,9 +455,7 @@ def _parse_top_mentions( top_mentions_type_0 = [] _top_mentions_type_0 = data for top_mentions_type_0_item_data in _top_mentions_type_0: - top_mentions_type_0_item = PolymarketTopMention.from_dict( - top_mentions_type_0_item_data - ) + top_mentions_type_0_item = PolymarketTopMention.from_dict(top_mentions_type_0_item_data) top_mentions_type_0.append(top_mentions_type_0_item) @@ -439,6 +466,23 @@ def _parse_top_mentions( top_mentions = _parse_top_mentions(d.pop("top_mentions", UNSET)) + def _parse_pulse(data: object) -> None | PolymarketTickerPulse | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + pulse_type_0 = PolymarketTickerPulse.from_dict(data) + + return pulse_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | PolymarketTickerPulse | Unset, data) + + pulse = _parse_pulse(d.pop("pulse", UNSET)) + polymarket_stock_detail_response = cls( ticker=ticker, found=found, @@ -459,6 +503,7 @@ def _parse_top_mentions( total_liquidity=total_liquidity, daily_trend=daily_trend, top_mentions=top_mentions, + pulse=pulse, ) polymarket_stock_detail_response.additional_properties = d diff --git a/src/adanos/_generated/models/polymarket_ticker_pulse.py b/src/adanos/_generated/models/polymarket_ticker_pulse.py new file mode 100644 index 0000000..af23380 --- /dev/null +++ b/src/adanos/_generated/models/polymarket_ticker_pulse.py @@ -0,0 +1,114 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.polymarket_ticker_pulse_mood import PolymarketTickerPulseMood +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.polymarket_pulse_evidence import PolymarketPulseEvidence + + +T = TypeVar("T", bound="PolymarketTickerPulse") + + +@_attrs_define +class PolymarketTickerPulse: + """Compact interpretation layer for current ticker-level Polymarket data. + + Attributes: + mood (PolymarketTickerPulseMood): Current compact Polymarket interpretation for this ticker + confidence (float): Interpretation confidence capped by coverage, trade breadth, spread, liquidity and recency + thin_data (bool): True when current evidence is insufficient for a strong directional interpretation + why (list[str]): Stable machine-readable reason codes explaining the pulse interpretation + evidence (PolymarketPulseEvidence): Compact data-quality evidence for the ticker-level Polymarket pulse. + warnings (list[str] | Unset): Stable machine-readable data quality, freshness and tradability warnings + """ + + mood: PolymarketTickerPulseMood + confidence: float + thin_data: bool + why: list[str] + evidence: PolymarketPulseEvidence + warnings: list[str] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + mood = self.mood.value + + confidence = self.confidence + + thin_data = self.thin_data + + why = self.why + + evidence = self.evidence.to_dict() + + warnings: list[str] | Unset = UNSET + if not isinstance(self.warnings, Unset): + warnings = self.warnings + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "mood": mood, + "confidence": confidence, + "thin_data": thin_data, + "why": why, + "evidence": evidence, + } + ) + if warnings is not UNSET: + field_dict["warnings"] = warnings + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.polymarket_pulse_evidence import PolymarketPulseEvidence + + d = dict(src_dict) + mood = PolymarketTickerPulseMood(d.pop("mood")) + + confidence = d.pop("confidence") + + thin_data = d.pop("thin_data") + + why = cast(list[str], d.pop("why")) + + evidence = PolymarketPulseEvidence.from_dict(d.pop("evidence")) + + warnings = cast(list[str], d.pop("warnings", UNSET)) + + polymarket_ticker_pulse = cls( + mood=mood, + confidence=confidence, + thin_data=thin_data, + why=why, + evidence=evidence, + warnings=warnings, + ) + + polymarket_ticker_pulse.additional_properties = d + return polymarket_ticker_pulse + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/adanos/_generated/models/polymarket_ticker_pulse_mood.py b/src/adanos/_generated/models/polymarket_ticker_pulse_mood.py new file mode 100644 index 0000000..8a8c326 --- /dev/null +++ b/src/adanos/_generated/models/polymarket_ticker_pulse_mood.py @@ -0,0 +1,13 @@ +from enum import Enum + + +class PolymarketTickerPulseMood(str, Enum): + BEARISH = "bearish" + BULLISH = "bullish" + EVENT_DRIVEN = "event_driven" + ILLIQUID = "illiquid" + MIXED = "mixed" + UNCLEAR = "unclear" + + def __str__(self) -> str: + return str(self.value) diff --git a/src/adanos/_generated/models/stock_sentiment_daily_trend_type_0_item.py b/src/adanos/_generated/models/stock_sentiment_daily_trend_type_0_item.py index 28267d1..ef538c4 100644 --- a/src/adanos/_generated/models/stock_sentiment_daily_trend_type_0_item.py +++ b/src/adanos/_generated/models/stock_sentiment_daily_trend_type_0_item.py @@ -19,6 +19,8 @@ class StockSentimentDailyTrendType0Item: mentions: int sentiment_score: float | None | Unset = UNSET buzz_score: float | None | Unset = UNSET + bullish_pct: int | None | Unset = UNSET + bearish_pct: int | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -29,6 +31,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["sentiment_score"] = self.sentiment_score if self.buzz_score is not UNSET: field_dict["buzz_score"] = self.buzz_score + if self.bullish_pct is not UNSET: + field_dict["bullish_pct"] = self.bullish_pct + if self.bearish_pct is not UNSET: + field_dict["bearish_pct"] = self.bearish_pct return field_dict @classmethod @@ -47,6 +53,8 @@ def _parse_float(data: object) -> float | None | Unset: mentions=d.pop("mentions"), sentiment_score=_parse_float(d.pop("sentiment_score", UNSET)), buzz_score=_parse_float(d.pop("buzz_score", UNSET)), + bullish_pct=cast(int | None | Unset, d.pop("bullish_pct", UNSET)), + bearish_pct=cast(int | None | Unset, d.pop("bearish_pct", UNSET)), ) item.additional_properties = d return item diff --git a/src/adanos/_generated/models/unsupported_asset_error.py b/src/adanos/_generated/models/unsupported_asset_error.py new file mode 100644 index 0000000..705357a --- /dev/null +++ b/src/adanos/_generated/models/unsupported_asset_error.py @@ -0,0 +1,68 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.unsupported_asset_error_detail import UnsupportedAssetErrorDetail + + +T = TypeVar("T", bound="UnsupportedAssetError") + + +@_attrs_define +class UnsupportedAssetError: + """Error response for unsupported v1 stock/crypto asset requests. + + Attributes: + detail (UnsupportedAssetErrorDetail): Structured detail for unsupported v1 stock/crypto asset requests. + """ + + detail: UnsupportedAssetErrorDetail + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + detail = self.detail.to_dict() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "detail": detail, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.unsupported_asset_error_detail import UnsupportedAssetErrorDetail + + d = dict(src_dict) + detail = UnsupportedAssetErrorDetail.from_dict(d.pop("detail")) + + unsupported_asset_error = cls( + detail=detail, + ) + + unsupported_asset_error.additional_properties = d + return unsupported_asset_error + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/adanos/_generated/models/unsupported_asset_error_detail.py b/src/adanos/_generated/models/unsupported_asset_error_detail.py new file mode 100644 index 0000000..79972bb --- /dev/null +++ b/src/adanos/_generated/models/unsupported_asset_error_detail.py @@ -0,0 +1,70 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="UnsupportedAssetErrorDetail") + + +@_attrs_define +class UnsupportedAssetErrorDetail: + """Structured detail for unsupported v1 stock/crypto asset requests. + + Attributes: + error_code (str): Machine-readable unsupported asset error code + message (str): Human-readable unsupported asset message + """ + + error_code: str + message: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + error_code = self.error_code + + message = self.message + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "error_code": error_code, + "message": message, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + error_code = d.pop("error_code") + + message = d.pop("message") + + unsupported_asset_error_detail = cls( + error_code=error_code, + message=message, + ) + + unsupported_asset_error_detail.additional_properties = d + return unsupported_asset_error_detail + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/adanos/_generated/models/x_daily_trend_item.py b/src/adanos/_generated/models/x_daily_trend_item.py index 9c4bbc2..0a5610b 100644 --- a/src/adanos/_generated/models/x_daily_trend_item.py +++ b/src/adanos/_generated/models/x_daily_trend_item.py @@ -20,12 +20,16 @@ class XDailyTrendItem: mentions (int): Number of tweet mentions on this date sentiment_score (float | None | Unset): Canonical average sentiment score for the day buzz_score (float | None | Unset): Buzz score for this date (0-100) + bullish_pct (int | None | Unset): Bullish tweet percentage for this date + bearish_pct (int | None | Unset): Bearish tweet percentage for this date """ date: str mentions: int sentiment_score: float | None | Unset = UNSET buzz_score: float | None | Unset = UNSET + bullish_pct: int | None | Unset = UNSET + bearish_pct: int | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -45,6 +49,10 @@ def to_dict(self) -> dict[str, Any]: else: buzz_score = self.buzz_score + bullish_pct = self.bullish_pct + + bearish_pct = self.bearish_pct + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -57,6 +65,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["sentiment_score"] = sentiment_score if buzz_score is not UNSET: field_dict["buzz_score"] = buzz_score + if bullish_pct is not UNSET: + field_dict["bullish_pct"] = bullish_pct + if bearish_pct is not UNSET: + field_dict["bearish_pct"] = bearish_pct return field_dict @@ -85,11 +97,17 @@ def _parse_buzz_score(data: object) -> float | None | Unset: buzz_score = _parse_buzz_score(d.pop("buzz_score", UNSET)) + bullish_pct = cast(int | None | Unset, d.pop("bullish_pct", UNSET)) + + bearish_pct = cast(int | None | Unset, d.pop("bearish_pct", UNSET)) + x_daily_trend_item = cls( date=date, mentions=mentions, sentiment_score=sentiment_score, buzz_score=buzz_score, + bullish_pct=bullish_pct, + bearish_pct=bearish_pct, ) x_daily_trend_item.additional_properties = d diff --git a/src/adanos/_generated/models/x_trending_stock.py b/src/adanos/_generated/models/x_trending_stock.py index 454f5c4..7cf2e50 100644 --- a/src/adanos/_generated/models/x_trending_stock.py +++ b/src/adanos/_generated/models/x_trending_stock.py @@ -6,6 +6,7 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.x_trending_stock_trend import XTrendingStockTrend from ..types import UNSET, Unset T = TypeVar("T", bound="XTrendingStock") @@ -15,15 +16,18 @@ class XTrendingStock: """Trending stock on X/Twitter - unified format matching Reddit API structure. - V5.4: Uses real tweet data from x_mentions (collected via twscrape). - All metrics now available - sentiment, upvotes, author diversity. + V5.5: Uses real tweet data from x_mentions (collected via twscrape). + Author diversity now prefers HHI-based effective authors from + author_distribution and falls back to scaled unique_authors only when the + full distribution is unavailable. Attributes: ticker (str): Stock ticker symbol - buzz_score (float): V5.4 buzz score from real tweet data. Components: mentions (20), sentiment (20), quality - (10), author diversity (14, HHI-based), trend (-10 to +20). Asymptotic scaling caps at 100. - trend (str): Multi-Factor Activity Score trend (24h vs previous 24h). 60% rank + 25% upvotes + 15% author - diversity. rising: >10% improvement. falling: >10% decline. stable: ±10%. + buzz_score (float | None): V5.5 buzz score from real tweet data. Components: mentions (20), sentiment (20), + quality (10), author diversity (14, HHI-based when author_distribution is available, else scaled + unique_authors), trend (-10 to +20). Asymptotic scaling caps at 100. + trend (XTrendingStockTrend): Activity momentum over the current 3 UTC days vs previous 3 UTC days, not price + movement or Grok rank movement. mentions (int): Number of tweet mentions from x_mentions table company_name (None | str | Unset): Company name from ticker_reference sentiment_score (float | None | Unset): Average sentiment score from tweet analysis (-1 to +1) @@ -31,13 +35,14 @@ class XTrendingStock: bearish_pct (int | None | Unset): Percentage of bearish tweet mentions total_upvotes (int | None | Unset): Total likes across all tweet mentions unique_tweets (int | None | Unset): Number of unique tweets mentioning this ticker (distinct tweet_id) - trend_history (list[float] | Unset): Daily buzz scores (oldest to newest). Length = max(days, 7). The last - element equals the current `buzz_score`. + trend_history (list[float] | Unset): Daily buzz scores (oldest→newest). Length follows the resolved period, with + a minimum of 7 values. For live windows, the final value is the current live buzz_score; closed historical + windows end at `to`. """ ticker: str - buzz_score: float - trend: str + buzz_score: float | None + trend: XTrendingStockTrend | str mentions: int company_name: None | str | Unset = UNSET sentiment_score: float | None | Unset = UNSET @@ -51,9 +56,10 @@ class XTrendingStock: def to_dict(self) -> dict[str, Any]: ticker = self.ticker + buzz_score: float | None buzz_score = self.buzz_score - trend = self.trend + trend = self.trend.value if isinstance(self.trend, XTrendingStockTrend) else self.trend mentions = self.mentions @@ -129,9 +135,14 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) ticker = d.pop("ticker") - buzz_score = d.pop("buzz_score") + def _parse_buzz_score(data: object) -> float | None: + if data is None: + return data + return cast(float | None, data) + + buzz_score = _parse_buzz_score(d.pop("buzz_score")) - trend = d.pop("trend") + trend = XTrendingStockTrend(d.pop("trend")) mentions = d.pop("mentions") diff --git a/src/adanos/_generated/models/x_trending_stock_trend.py b/src/adanos/_generated/models/x_trending_stock_trend.py new file mode 100644 index 0000000..a8546f8 --- /dev/null +++ b/src/adanos/_generated/models/x_trending_stock_trend.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class XTrendingStockTrend(str, Enum): + FALLING = "falling" + RISING = "rising" + STABLE = "stable" + + def __str__(self) -> str: + return str(self.value) diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index f2027a0..2c498b0 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -46,6 +46,8 @@ def request_params(route) -> dict: "mentions": 61, "sentiment_score": 0.245, "buzz_score": 71.2, + "bullish_pct": 62, + "bearish_pct": 18, } ], } @@ -266,6 +268,8 @@ def request_params(route) -> dict: "trade_count": 8, "sentiment_score": 0.114, "buzz_score": 71.4, + "bullish_pct": 64, + "bearish_pct": 21, } ], "top_mentions": [ @@ -279,6 +283,20 @@ def request_params(route) -> dict: "market_status": "tradable", } ], + "pulse": { + "mood": "mixed", + "confidence": 60.0, + "thin_data": False, + "why": ["opposing_market_signals"], + "warnings": ["high_average_spread"], + "evidence": { + "directional_coverage": 1.0, + "traded_market_pct": 0.231, + "zero_trade_market_pct": 0.769, + "avg_spread": 0.099, + "snapshot_at": "2026-06-24T06:25:53Z", + }, + }, } POLYMARKET_COMPARE_RESPONSE = { @@ -1181,8 +1199,11 @@ def test_stock(self, client): assert result.found is True assert result.current_market_count == 2 assert result.daily_trend[0].sentiment_score == 0.114 + assert result.daily_trend[0].bullish_pct == 64 assert "sentiment" not in result.daily_trend[0].to_dict() assert result.top_mentions[0].market_status == "tradable" + assert result.pulse.mood.value == "mixed" + assert result.pulse.evidence.directional_coverage == 1.0 @respx.mock def test_mentions(self, client): @@ -1247,6 +1268,29 @@ def test_compare(self, client): assert result.stocks[0].current_market_count == 2 assert result.stocks[0].trend_history[-1] == 71.4 + @respx.mock + def test_compare_limit_returns_structured_error(self, client): + from adanos._generated.models import CompareLimitError + + respx.get(f"{BASE_URL}/polymarket/stocks/v1/compare").mock( + return_value=httpx.Response( + 400, + json={ + "detail": { + "error": "too_many_tickers", + "message": "Too many tickers.", + "max_items": 10, + "item_name": "ticker", + } + }, + ) + ) + + result = client.polymarket.compare(["AAPL"] * 11) + + assert isinstance(result, CompareLimitError) + assert result.detail.max_items == 10 + class TestPolymarketMarketSentiment: @respx.mock @@ -1260,6 +1304,34 @@ def test_market_sentiment(self, client): assert result.current_market_count == 64 assert result.drivers[0].trade_count == 52 + @respx.mock + def test_market_sentiment_allows_unknown_trader_coverage(self, client): + payload = {**POLYMARKET_MARKET_SENTIMENT, "unique_traders": None} + respx.get(f"{BASE_URL}/polymarket/stocks/v1/market-sentiment").mock( + return_value=httpx.Response(200, json=payload) + ) + + result = client.polymarket.market_sentiment(days=365) + + assert result.unique_traders is None + + def test_generated_model_keeps_legacy_positional_constructor_order(self): + from adanos._generated.models import PolymarketMarketSentimentResponse + + result = PolymarketMarketSentimentResponse(50.0, 1, 2, 3, 4, 5.0, 6, 7, 8, 9, 10, 11) + + assert result.unique_traders == 4 + assert result.total_liquidity == 5.0 + + +class TestXTrendingStockCompatibility: + def test_generated_model_serializes_legacy_string_trend(self): + from adanos._generated.models import XTrendingStock + + result = XTrendingStock("AAPL", 50.0, "rising", 10) + + assert result.to_dict()["trend"] == "rising" + class TestPeriodParams: @respx.mock @@ -1346,6 +1418,27 @@ def test_401_returns_error_response(self, client): result = client.reddit.trending() assert result.detail == "Invalid API key" + @respx.mock + def test_404_returns_unsupported_asset_error(self, client): + from adanos._generated.models import UnsupportedAssetError + + respx.get(f"{BASE_URL}/reddit/stocks/v1/stock/NOPE").mock( + return_value=httpx.Response( + 404, + json={ + "detail": { + "error_code": "unsupported_ticker", + "message": "Unsupported ticker.", + } + }, + ) + ) + + result = client.reddit.stock("NOPE") + + assert isinstance(result, UnsupportedAssetError) + assert result.detail.error_code == "unsupported_ticker" + @respx.mock def test_429_returns_error_response(self, client): """429 is a documented status — returns ErrorResponse.""" @@ -1377,6 +1470,29 @@ def test_422_invalid_period_returns_structured_error(self, client): assert result.detail.available_since.isoformat() == "2026-03-01" assert result.to_dict() == payload + @respx.mock + def test_422_data_unavailable_returns_structured_period_error(self, client): + from adanos._generated.models import InvalidPeriodError + + payload = { + "detail": { + "error": "data_unavailable", + "message": "Requested period predates public data.", + "field": "from", + "value": "2020-01-01", + "available_since": "2025-01-01", + } + } + respx.get(f"{BASE_URL}/reddit/stocks/v1/trending").mock( + return_value=httpx.Response(422, json=payload) + ) + + result = client.reddit.trending(from_="2020-01-01", to="2020-01-07") + + assert isinstance(result, InvalidPeriodError) + assert result.detail.error == "data_unavailable" + assert result.detail.field == "from" + @respx.mock def test_422_non_period_dict_detail_is_preserved(self, client): """Non-period custom 422 envelopes should remain generic validation responses.""" @@ -1404,6 +1520,48 @@ def test_invalid_period_error_model_round_trips_dates(self): assert result.detail.period_from.isoformat() == "2026-01-01" assert result.to_dict() == payload + def test_api_149_structured_error_models_round_trip(self): + from adanos._generated.models import ( + CompareLimitError, + InvalidPeriodError, + UnsupportedAssetError, + ) + + period_payload = { + "detail": { + "error": "data_unavailable", + "message": "Requested period predates public data.", + "field": "from", + "value": "2020-01-01", + "today": "2026-08-09", + "period_from": "2020-01-01", + "period_to": "2020-01-07", + "available_since": "2025-01-01", + "retention_from": "2025-07-01", + "requested_days": 7, + "max_days": 365, + "platform": "reddit-stocks", + } + } + compare_payload = { + "detail": { + "error": "too_many_tickers", + "message": "Too many tickers.", + "max_items": 10, + "item_name": "ticker", + } + } + unsupported_payload = { + "detail": { + "error_code": "unsupported_ticker", + "message": "Unsupported ticker.", + } + } + + assert InvalidPeriodError.from_dict(period_payload).to_dict() == period_payload + assert CompareLimitError.from_dict(compare_payload).to_dict() == compare_payload + assert UnsupportedAssetError.from_dict(unsupported_payload).to_dict() == unsupported_payload + @respx.mock def test_422_non_validation_list_detail_is_preserved(self, client): """Unexpected 422 list envelopes should be preserved instead of parsed as validation errors."""