Skip to main content

Crate brokapi_finam

Crate brokapi_finam 

Source
Expand description

Finam connectors: market data and user data over the Finam Trade API (gRPC).

This is the connector layer. It implements the shared traits of brokapi-core on top of the protocol layer (brokapi-finam-protocol), the sans-io logic (brokapi-sansio) and the runtime pieces (brokapi-runtime: rate limiter, command gate, shutdown).

TypeRoleTraits
MarketDataConnectororder books, trades, quotes, candles, instrument directory. Not tied to an accountOrderBookSource, MarketDataSource, InstrumentSource
UserDataConnectororders, stop orders, own trades, portfolio of ONE accountOrderExecutor, StopOrderExecutor, ExecutionSource, PortfolioSource
FinamRawany other Finam method, with the connector’s token and rate limiternone, see connector.raw()

Things that are true for the whole crate:

  • One user data connector is one account. To trade two accounts, start two connectors. They can share one token manager (FinamApiConfig::shared_tokens) and must share one rate limiter.
  • One rate limiter per Finam user. Finam documents one request quota for the whole API. The bundled limits (limits::default_limits) are meant to be shared by every connector of the user.
  • A place command that got no answer is never repeated. A timeout or a broken connection gives Error::Unknown, because a repeat could create a second order. Ask the order state or call reconcile to learn what happened.
  • A rejected order is a final answer. Error::Rejected means the broker did not take the order.
  • Quantity is in pieces (units of the instrument), as everywhere in the Finam API and in this library, not in lots.
  • Instruments are SYMBOL@MIC (for example SBER@MISX), carried as NativeId::SymbolMic.

Finam has no sandbox. The examples in this documentation run against an in-process imitation of the broker (brokapi-mocks). The imitation is written from the broker documentation. It does not prove how the live broker behaves.

The book with the full guide: https://brokapi.ru/docs/

§Examples

Read an order book, then place a limit order far from the market and cancel it:

use brokapi_core::{
    ClientOrderId, InstrumentId, InstrumentKey, NativeId, OrderBook, OrderBookSource, OrderExecutor,
    OrderType, PlaceOrderRequest, Price, Qty, ShutdownMode, Side,
};
use brokapi_finam::limits::default_limits;
use brokapi_finam::{MarketDataConfig, MarketDataConnector, UserDataConfig, UserDataConnector};
use brokapi_runtime::BrokerLimiter;
use tokio::sync::mpsc;

// `api` holds your secret (and the endpoint of the real broker by default).
// One limiter per Finam user, shared by every connector.
let limiter = BrokerLimiter::new(&default_limits());
let (events, _rx) = mpsc::channel(256);

let md = MarketDataConnector::start(
    MarketDataConfig::new(api.clone(), "finam-md"),
    limiter.clone(),
    events.clone(),
)
.await?;
let sber = InstrumentId::new(
    InstrumentKey::new("SBER", "MISX"),
    NativeId::SymbolMic { symbol: "SBER".into(), mic: "MISX".into() },
);
let book = md.order_book(&sber, 5).await?;
assert!(matches!(book, OrderBook::Snapshot { .. }));

let ud = UserDataConnector::start(
    UserDataConfig::new(api, account, "finam-ud"),
    limiter,
    events,
)
.await?;
// Orders are refused until the connector is reconciled with the broker (empty ledger here).
ud.reconcile(&[]).await?;
let cid = ClientOrderId::new_v4();
let ack = ud
    .place(PlaceOrderRequest {
        cid,
        instrument: sber,
        side: Side::Buy,
        order_type: OrderType::Limit,
        qty: Qty::from(1),
        price: Some(Price::from(1)),
    })
    .await?;
assert_eq!(ack.cid, cid);
ud.cancel(cid).await?;

md.shutdown(ShutdownMode::Immediate).await;
ud.shutdown(ShutdownMode::Immediate).await;

connector.raw() (FinamRaw) reaches any other method of the API with the connector’s token, endpoint and rate limiter.

Re-exports§

pub use cid::FinamCidCodec;
pub use config::FinamApiConfig;
pub use config::MarketDataConfig;
pub use config::UserDataConfig;
pub use config::api_config_from_env;
pub use core::MdCore;
pub use core::SubStatus;
pub use core::UdCore;
pub use md::MarketDataConnector;
pub use raw::FinamRaw;
pub use ud::UserDataConnector;

Modules§

cid
Client order id codec
config
Connector configuration: the credentials and endpoint shared by both roles (FinamApiConfig) and the settings of each role (MarketDataConfig, UserDataConfig).
core
Sans-io cores: frames in, normalized events out. No sockets, timers or tasks here.
error
Map protocol errors to public connector errors.
index
Client order id <-> Finam order id.
limits
Rate limits of the Finam connectors, loaded from the bundled limits.toml.
map
Translation between Finam protobuf messages and brokapi-core types.
md
Finam market data connector: MarketDataConnector.
pump
Event pump: frames -> core -> per-subscription buffers -> the client’s Sender.
raw
Direct access to any Finam Trade API method (“back door”): same secret and token manager, same endpoint, same [BrokerLimiter] as the connector it came from.
rpc
Unary call helper: deadline, one re-auth retry for reads.
stream
One supervised gRPC server-stream: open, read, reopen with backoff.
subs
Subscription id generator (unique within one connector).
ud
Finam user data connector: UserDataConnector. One connector = one account.
util
Shared helpers: instrument ids, timestamps, decimals.