diff --git a/.secrets.baseline b/.secrets.baseline index 0a39759..e2c4104 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -137,5 +137,5 @@ } ] }, - "generated_at": "2025-05-16T12:57:35Z" + "generated_at": "2025-07-27T08:05:02Z" } diff --git a/examples/assets.py b/examples/assets.py index 3b44347..6588dc1 100644 --- a/examples/assets.py +++ b/examples/assets.py @@ -5,6 +5,7 @@ from finam_trade_api import Client, TokenManager token = os.getenv("TOKEN") +account_id = os.getenv("ACCOUNT_ID") underlying_symbol = "YDEX@RTSX" instrument_symbol = "YDEX@MISX" @@ -23,9 +24,9 @@ async def main(): except NotImplementedError as e: print("Метод get_assets не реализован:", e) - pprint(await client.assets.get_asset(instrument_symbol, "1346867")) + pprint(await client.assets.get_asset(instrument_symbol, account_id)) - await client.assets.get_asset_params(instrument_symbol, "1346867") + await client.assets.get_asset_params(instrument_symbol, account_id) if __name__ == "__main__": diff --git a/finam_trade_api/access/model.py b/finam_trade_api/access/model.py index e340f35..465f9f5 100644 --- a/finam_trade_api/access/model.py +++ b/finam_trade_api/access/model.py @@ -4,8 +4,8 @@ class MDPermission(BaseModel): - quoteLevel: str - delayMinutes: int + quote_level: str + delay_minutes: int mic: str country: str | None = None continent: str | None = None @@ -13,7 +13,7 @@ class MDPermission(BaseModel): class TokenDetailsResponse(BaseModel): - createdAt: datetime - expiresAt: datetime - mdPermissions: list[MDPermission] - accountIds: list[str] + created_at: datetime + expires_at: datetime + md_permissions: list[MDPermission] + account_ids: list[str] diff --git a/finam_trade_api/account/__init__.py b/finam_trade_api/account/__init__.py index d562f6f..fd5b072 100644 --- a/finam_trade_api/account/__init__.py +++ b/finam_trade_api/account/__init__.py @@ -6,7 +6,6 @@ GetTradesResponse, GetTransactionsRequest, GetTransactionsResponse, - MoneyChange, Position, Trade, Transaction, diff --git a/finam_trade_api/account/model.py b/finam_trade_api/account/model.py index 7ad0b7d..ecbb2ee 100644 --- a/finam_trade_api/account/model.py +++ b/finam_trade_api/account/model.py @@ -2,24 +2,24 @@ from pydantic import BaseModel, Field -from finam_trade_api.base_client.models import FinamDecimal +from finam_trade_api.base_client.models import FinamDecimal, FinamMoney class Position(BaseModel): symbol: str quantity: FinamDecimal - averagePrice: FinamDecimal - currentPrice: FinamDecimal + average_price: FinamDecimal + current_price: FinamDecimal class GetAccountResponse(BaseModel): - accountId: str + account_id: str type: str status: str equity: FinamDecimal - unrealizedProfit: FinamDecimal + unrealized_profit: FinamDecimal positions: list[Position] = Field(default_factory=list) - cash: list = Field(default_factory=list) # todo не задокументировано + cash: list[FinamMoney] = Field(default_factory=list) class GetTransactionsRequest(BaseModel): @@ -33,16 +33,10 @@ class GetTradesRequest(GetTransactionsRequest): ... -class MoneyChange(BaseModel): - currencyCode: str - units: str - nanos: int - - class Trade(BaseModel): size: FinamDecimal price: FinamDecimal - accruedInterest: FinamDecimal + accrued_interest: FinamDecimal class Transaction(BaseModel): @@ -50,7 +44,7 @@ class Transaction(BaseModel): category: str timestamp: str symbol: str - change: MoneyChange | None = None + change: FinamMoney | None = None trade: Trade | None = None @@ -59,7 +53,7 @@ class GetTransactionsResponse(BaseModel): class AccountTrade(BaseModel): - tradeId: str + trade_id: str symbol: str price: FinamDecimal size: FinamDecimal diff --git a/finam_trade_api/assets/model.py b/finam_trade_api/assets/model.py index 63323c3..4fd6ffc 100644 --- a/finam_trade_api/assets/model.py +++ b/finam_trade_api/assets/model.py @@ -17,9 +17,9 @@ class ExchangesResponse(BaseModel): class Option(BaseModel): symbol: str type: str - contractSize: FinamDecimal - tradeFirstDay: FinamDate | None = None - tradeLastDay: FinamDate + contract_size: FinamDecimal + trade_first_day: FinamDate | None = None + trade_last_day: FinamDate strike: FinamDecimal multiplier: FinamDecimal | None = None @@ -30,8 +30,8 @@ class OptionsChainResponse(BaseModel): class SessionInterval(BaseModel): - startTime: datetime - endTime: datetime + start_time: datetime + end_time: datetime class Session(BaseModel): @@ -64,26 +64,26 @@ class AssetsResponse(BaseModel): class AssetResponse(BaseAssetModel): board: str decimals: int - minStep: str - lotSize: FinamDecimal - expirationDate: str | None = None + min_step: str + lot_size: FinamDecimal + expiration_date: str | None = None class Status(BaseModel): value: str - haltedDays: int = 0 + halted_days: int = 0 class AssetParamsResponse(BaseModel): symbol: str - accountId: str + account_id: str tradeable: bool longable: Status shortable: Status - longRiskRate: FinamDecimal | None = None - longCollateral: FinamMoney | None = None - shortRiskRate: FinamDecimal | None = None - shortCollateral: FinamMoney | None = None + long_risk_rate: FinamDecimal | None = None + long_collateral: FinamMoney | None = None + short_risk_rate: FinamDecimal | None = None + short_collateral: FinamMoney | None = None class ClockResponse(BaseModel): diff --git a/finam_trade_api/base_client/models.py b/finam_trade_api/base_client/models.py index 89fbc45..b91320e 100644 --- a/finam_trade_api/base_client/models.py +++ b/finam_trade_api/base_client/models.py @@ -22,5 +22,5 @@ class FinamMoney(BaseModel): A custom money type for Finam API responses. """ units: str = "0" - currencyCode: str = "RUB" + currency_code: str = "RUB" nanos: int = 0 diff --git a/finam_trade_api/instruments/model.py b/finam_trade_api/instruments/model.py index f4e18c3..d6b2118 100644 --- a/finam_trade_api/instruments/model.py +++ b/finam_trade_api/instruments/model.py @@ -57,11 +57,11 @@ class Quote(BaseModel): symbol: str | None = None timestamp: datetime ask: FinamDecimal - askSize: FinamDecimal + ask_size: FinamDecimal bid: FinamDecimal - bidSize: FinamDecimal + bid_size: FinamDecimal last: FinamDecimal - lastSize: FinamDecimal + last_size: FinamDecimal volume: FinamDecimal turnover: FinamDecimal open: FinamDecimal @@ -76,7 +76,7 @@ class QuoteResponse(BaseResponse): class Trade(BaseModel): - tradeId: str + trade_id: str mpid: str = "" timestamp: datetime price: FinamDecimal @@ -89,8 +89,8 @@ class TradesResponse(BaseResponse): class OrderBookRow(BaseModel): price: FinamDecimal - sellSize: FinamDecimal | None = None - buySize: FinamDecimal | None = None + sell_size: FinamDecimal | None = None + buy_size: FinamDecimal | None = None action: OrderBookRowAction mpid: str = "" timestamp: datetime diff --git a/pyproject.toml b/pyproject.toml index 834a6ec..32bc7ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "finam-trade-api" -version = "4.0.3" +version = "4.1.0" description = "Асинхронный REST-клиент для API Finam" authors = ["DBoyara "] license = "GNU GPL v.3.0" diff --git a/tests/access/test_access_token.py b/tests/access/test_access_token.py index 56b2e80..a690dd8 100644 --- a/tests/access/test_access_token.py +++ b/tests/access/test_access_token.py @@ -43,14 +43,14 @@ async def test_returns_token_details_on_successful_request(): client = TokenClient(token_manager) token_details = { - "createdAt": datetime.now(), - "expiresAt": datetime.now(), - "accountIds": ["1"], - "mdPermissions": [{"quoteLevel": "quoteLevel", "delayMinutes": 0, "mic": "mic"}] + "created_at": datetime.now(), + "expires_at": datetime.now(), + "account_ids": ["1"], + "md_permissions": [{"quote_level": "quoteLevel", "delay_minutes": 0, "mic": "mic"}] } with patch.object(client, "_exec_request", return_value=(token_details, True)): result = await client.get_jwt_token_details() assert isinstance(result, TokenDetailsResponse) - assert result.createdAt - assert result.expiresAt - assert result.accountIds and "1" in result.accountIds + assert result.created_at + assert result.expires_at + assert result.account_ids and "1" in result.account_ids diff --git a/tests/account/test_account.py b/tests/account/test_account.py index 35d28b0..a75ef76 100644 --- a/tests/account/test_account.py +++ b/tests/account/test_account.py @@ -26,11 +26,11 @@ async def test_get_account_info_success(account_client): account_id = "account123" # Создаем данные-заглушку на основе модели GetAccountResponse response_data = { - "accountId": account_id, + "account_id": account_id, "type": "broker", "status": "active", "equity": {"value": "1000.0"}, - "unrealizedProfit": {"value": "50.0"}, + "unrealized_profit": {"value": "50.0"}, "positions": [], "cash": [] } @@ -41,7 +41,7 @@ async def test_get_account_info_success(account_client): f"/accounts/{account_id}", ) assert isinstance(result, GetAccountResponse) - assert result.accountId == account_id + assert result.account_id == account_id @pytest.mark.asyncio async def test_get_account_info_failure(account_client): @@ -114,7 +114,7 @@ async def test_get_trades_success(account_client): response_data = { "trades": [ { - "tradeId": "t1", + "trade_id": "t1", "symbol": "AAPL", "price": {"value": "150.0"}, "size": {"value": "10.0"}, @@ -136,7 +136,7 @@ async def test_get_trades_success(account_client): ) assert isinstance(result, GetTradesResponse) assert len(result.trades) == 1 - assert result.trades[0].tradeId == "t1" + assert result.trades[0].trade_id == "t1" @pytest.mark.asyncio async def test_get_trades_failure(account_client): diff --git a/tests/assets/test_assets.py b/tests/assets/test_assets.py index 4198aa8..b60cdba 100644 --- a/tests/assets/test_assets.py +++ b/tests/assets/test_assets.py @@ -46,8 +46,8 @@ async def test_get_options_chain_success(assets_client): "options": [{ "symbol": "AAPL2022-12-31C150", "type": "call", - "contractSize": {"value": "1.0"}, - "tradeLastDay": {"year":2022, "month": 12, "day": 31}, + "contract_size": {"value": "1.0"}, + "trade_last_day": {"year":2022, "month": 12, "day": 31}, "strike": {"value": "150.0"}, }] } @@ -76,7 +76,7 @@ async def test_get_schedule_success(assets_client): "symbol": symbol, "sessions": [{ "type": "regular", - "interval": {"startTime": "2023-01-01T09:30:00", "endTime": "2023-01-01T16:00:00"} + "interval": {"start_time": "2023-01-01T09:30:00", "end_time": "2023-01-01T16:00:00"} }] } with patch.object(assets_client, "_exec_request", return_value=(response_data, True)) as mock_exec: @@ -106,7 +106,7 @@ async def test_get_assets_not_implemented(assets_client): async def test_get_asset_success(assets_client): symbol = "AAPL" account_id = "account123" - response_data = {"id": "1", "ticker": "AAPL", "mic": "MIC123", "isin": "US0378331005", "type": "stock", "name": "Apple Inc.", "board": "TQBR", "decimals": 2, "minStep": "0.01", "lotSize": {"value": "10"}} + response_data = {"id": "1", "ticker": "AAPL", "mic": "MIC123", "isin": "US0378331005", "type": "stock", "name": "Apple Inc.", "board": "TQBR", "decimals": 2, "min_step": "0.01", "lot_size": {"value": "10"}} with patch.object(assets_client, "_exec_request", return_value=(response_data, True)) as mock_exec: result = await assets_client.get_asset(symbol, account_id) mock_exec.assert_called_once_with(assets_client.RequestMethod.GET, f"/assets/{symbol}", params={"account_id": account_id}) @@ -129,7 +129,7 @@ async def test_get_asset_failure(assets_client): async def test_get_asset_params_success(assets_client): symbol = "AAPL" account_id = "account123" - response_data = {"id": "1", "ticker": "AAPL", "mic": "MIC123", "isin": "US0378331005", "type": "stock", "name": "Apple Inc.", "symbol": "AAPL", "accountId": account_id, "tradeable": True, "longable": {"value": "yes", "haltedDays": 0}, "shortable": {"value": "no", "haltedDays": 0}} + response_data = {"id": "1", "ticker": "AAPL", "mic": "MIC123", "isin": "US0378331005", "type": "stock", "name": "Apple Inc.", "symbol": "AAPL", "account_id": account_id, "tradeable": True, "longable": {"value": "yes", "halted_days": 0}, "shortable": {"value": "no", "halted_days": 0}} with patch.object(assets_client, "_exec_request", return_value=(response_data, True)) as mock_exec: result = await assets_client.get_asset_params(symbol, account_id) mock_exec.assert_called_once_with(assets_client.RequestMethod.GET, f"/assets/{symbol}/params", params={"account_id": account_id}) diff --git a/tests/instruments/test_instrument.py b/tests/instruments/test_instrument.py index ea9a568..b6d27c5 100644 --- a/tests/instruments/test_instrument.py +++ b/tests/instruments/test_instrument.py @@ -73,19 +73,19 @@ async def test_get_last_quote_success(instrument_client): "ask": { "value": "4030.5" }, - "askSize": { + "ask_size": { "value": "90" }, "bid": { "value": "4030.0" }, - "bidSize": { + "bid_size": { "value": "25" }, "last": { "value": "4030.5" }, - "lastSize": { + "last_size": { "value": "39" }, "volume": {