Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,5 @@
}
]
},
"generated_at": "2025-05-16T12:57:35Z"
"generated_at": "2025-07-27T08:05:02Z"
}
5 changes: 3 additions & 2 deletions examples/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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__":
Expand Down
12 changes: 6 additions & 6 deletions finam_trade_api/access/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@


class MDPermission(BaseModel):
quoteLevel: str
delayMinutes: int
quote_level: str
delay_minutes: int
mic: str
country: str | None = None
continent: str | None = None
worldwide: bool = False


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]
1 change: 0 additions & 1 deletion finam_trade_api/account/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
GetTradesResponse,
GetTransactionsRequest,
GetTransactionsResponse,
MoneyChange,
Position,
Trade,
Transaction,
Expand Down
24 changes: 9 additions & 15 deletions finam_trade_api/account/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -33,24 +33,18 @@ 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):
id: str
category: str
timestamp: str
symbol: str
change: MoneyChange | None = None
change: FinamMoney | None = None
trade: Trade | None = None


Expand All @@ -59,7 +53,7 @@ class GetTransactionsResponse(BaseModel):


class AccountTrade(BaseModel):
tradeId: str
trade_id: str
symbol: str
price: FinamDecimal
size: FinamDecimal
Expand Down
28 changes: 14 additions & 14 deletions finam_trade_api/assets/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -30,8 +30,8 @@ class OptionsChainResponse(BaseModel):


class SessionInterval(BaseModel):
startTime: datetime
endTime: datetime
start_time: datetime
end_time: datetime


class Session(BaseModel):
Expand Down Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion finam_trade_api/base_client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 6 additions & 6 deletions finam_trade_api/instruments/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -76,7 +76,7 @@ class QuoteResponse(BaseResponse):


class Trade(BaseModel):
tradeId: str
trade_id: str
mpid: str = ""
timestamp: datetime
price: FinamDecimal
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "finam-trade-api"
version = "4.0.3"
version = "4.1.0"
description = "Асинхронный REST-клиент для API Finam"
authors = ["DBoyara <boyarshin.den@yandex.ru>"]
license = "GNU GPL v.3.0"
Expand Down
14 changes: 7 additions & 7 deletions tests/access/test_access_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 5 additions & 5 deletions tests/account/test_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": []
}
Expand All @@ -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):
Expand Down Expand Up @@ -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"},
Expand All @@ -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):
Expand Down
10 changes: 5 additions & 5 deletions tests/assets/test_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
}]
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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})
Expand All @@ -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})
Expand Down
6 changes: 3 additions & 3 deletions tests/instruments/test_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down