-
Notifications
You must be signed in to change notification settings - Fork 20
Add statements Data #171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add statements Data #171
Conversation
Reviewer's GuideThis PR removes support for older Python versions, upgrades dependencies and CI tooling, refactors client code with modern type hints and style, and introduces a new StatementClient (with related constants, models and tests) while adjusting the ASX market client and dozens of VCR cassettes to align with revamped endpoints and response formats. ER diagram for new NYSEUrl.statement endpointerDiagram
NYSEUrl ||--o{ StatementClient : uses
StatementClient ||--o{ Statement : fetches
Statement {
date date
quarter int
year int
}
NYSEUrl {
statement str
}
Class diagram for the new StatementClient and related modelsclassDiagram
class StatementClient {
+async list(request: StatementRequest) List[Statement]
}
class StatementRequest {
+str symbol
+date start_date
}
class Data {
+str data_code
+float value
}
class StatementData {
+List[Data] balance_sheet
+List[Data] income_statement
+List[Data] cash_flow
+List[Data] overview
}
class Statement {
+date date
+int quarter
+int year
+StatementData statement_data
}
StatementClient --|> BaseClient
StatementClient ..> StatementRequest
StatementClient ..> Statement
StatementData o-- Data
Statement o-- StatementData
Class diagram for StakeClient with StatementClient integrationclassDiagram
class StakeClient {
+equities
+fundings
+market
+orders
+products
+ratings
+trades
+transactions
+statements
+set_exchange(exchange)
+async get(url, payload)
+async post(url, payload)
+async delete(url, payload)
}
class StatementClient
StakeClient --> StatementClient : statements
Class diagram for updated ASX MarketClient and Status modelsclassDiagram
class MarketClient {
+async get() MarketStatus
+async is_open() bool
}
class MarketStatus {
+Optional[datetime] last_trading_date
+Status status
}
class Status {
+str current
}
MarketClient --|> BaseClient
MarketClient ..> MarketStatus
MarketStatus o-- Status
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @stabacco - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `stake/asx/market.py:27` </location>
<code_context>
async def get(self) -> MarketStatus:
data = await self._client.get(self._client.exchange.market_status)
- return MarketStatus(**data)
+ return MarketStatus(
+ last_trading_date=data[0]["lastTradedTimestamp"],
+ status=Status(current=data[0]["marketStatus"]),
</code_context>
<issue_to_address>
Directly indexing data[0] assumes a non-empty list response.
This could raise an IndexError if the list is empty. Please add a check to handle empty responses.
</issue_to_address>
### Comment 2
<location> `stake/statement.py:40` </location>
<code_context>
+ model_config = pydantic.ConfigDict(alias_generator=camelcase, populate_by_name=True)
+
+
+class StatementClient(BaseClient):
+ """This client is in charge listing the experts' statements for symbols."""
+
+ async def list(self, request: StatementRequest) -> List[Statement]:
+ """Lists all the statements for the symbols specified in the request.
+
+ Returns:
+ List[Statement]: The list of statements.
+ """
+ data = await self._client.get(
+ self._client.exchange.statement.format(
+ symbol=request.symbol,
+ date=request.start_date,
+ )
+ )
+
+ if data == {"message": "No data returned"}:
+ return []
+ return [Statement(**d) for d in data]
</code_context>
<issue_to_address>
No error handling for unexpected API response structure in StatementClient.list.
Catch pydantic ValidationError when parsing the API response to handle unexpected structures and provide clearer error messages or fallback behavior.
Suggested implementation:
```python
from pydantic import ValidationError
class Statement(pydantic.BaseModel):
date: date
quarter: int
year: int
statement_data: StatementData
model_config = pydantic.ConfigDict(alias_generator=camelcase, populate_by_name=True)
```
```python
if data == {"message": "No data returned"}:
return []
try:
return [Statement(**d) for d in data]
except ValidationError as e:
# You can customize this behavior as needed (e.g., log, return [], etc.)
raise RuntimeError(f"Failed to parse statement data: {e}") from e
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| async def get(self) -> MarketStatus: | ||
| data = await self._client.get(self._client.exchange.market_status) | ||
| return MarketStatus(**data) | ||
| return MarketStatus( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Directly indexing data[0] assumes a non-empty list response.
This could raise an IndexError if the list is empty. Please add a check to handle empty responses.
| class StatementClient(BaseClient): | ||
| """This client is in charge listing the experts' statements for symbols.""" | ||
|
|
||
| async def list(self, request: StatementRequest) -> List[Statement]: | ||
| """Lists all the statements for the symbols specified in the request. | ||
| Returns: | ||
| List[Statement]: The list of statements. | ||
| """ | ||
| data = await self._client.get( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): No error handling for unexpected API response structure in StatementClient.list.
Catch pydantic ValidationError when parsing the API response to handle unexpected structures and provide clearer error messages or fallback behavior.
Suggested implementation:
from pydantic import ValidationError
class Statement(pydantic.BaseModel):
date: date
quarter: int
year: int
statement_data: StatementData
model_config = pydantic.ConfigDict(alias_generator=camelcase, populate_by_name=True) if data == {"message": "No data returned"}:
return []
try:
return [Statement(**d) for d in data]
except ValidationError as e:
# You can customize this behavior as needed (e.g., log, return [], etc.)
raise RuntimeError(f"Failed to parse statement data: {e}") from e| self.trades: Union[ | ||
| asx.trade.TradesClient, trade.TradesClient | ||
| ] = asx.trade.TradesClient(self) | ||
| self.equities: Union[asx.equity.EquitiesClient, equity.EquitiesClient] = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Extract code out into method [×2] (extract-method)
Summary by Sourcery
Add support for retrieving financial statements and modernize project to Python 3.10+
New Features:
Enhancements:
Build:
CI:
Deployment:
Tests: