20 stable releases

2.32.3 Oct 5, 2024
2.31.0 Jul 5, 2024
2.29.0 Mar 24, 2024
2.27.2 Sep 22, 2023
0.15.0 Feb 28, 2021

#4 in Finance

MIT/Apache

115KB
3K SLoC

rust-tinkoff-invest

development stage: BETA

DO NOT use for production

API reference

get accounts

use tinkoff_invest::TinkoffInvest;

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let accounts = tinkoff.accounts().await?;

    println!("accounts: {:?}", accounts);

    Ok(())
}

get market instruments

use tinkoff_invest::{enums::InstrumentType, TinkoffInvest};

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let market_instruments = tinkoff
        .market_instruments(InstrumentType::Share)
        .await?;

    println!("{:?}", market_instruments);

    Ok(())
}

get candlesticks

use tinkoff_invest::{enums::CandlestickInterval, extra::chrono, types::Figi, TinkoffInvest};

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let figi = Figi::from("BBG004730N88");
    let from = chrono::NaiveDate::from_ymd(2020, 1, 10);
    let to = chrono::NaiveDate::from_ymd(2020, 1, 11);
    let candlesticks = tinkoff
        .candlesticks(&figi, CandlestickInterval::Min, from.into(), to.into())
        .await?;

    println!("{:?}", candlesticks);

    Ok(())
}

get order book

use tinkoff_invest::{types::Figi, TinkoffInvest};

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let figi = Figi::from("BBG004730N88");
    let order_book = tinkoff.order_book(&figi, 10).await?;

    println!("{:?}", order_book);

    Ok(())
}

get operations

use tinkoff_invest::{enums::OperationState, extra::chrono, types::Figi, TinkoffInvest};

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let accounts = tinkoff.accounts().await?;

    let first_account = accounts.get(0).unwrap().clone();

    tinkoff.set_account(Some(first_account));

    let figi = Figi::from("BBG004730N88");
    let from = chrono::NaiveDate::from_ymd(2020, 1, 1);
    let to = chrono::NaiveDate::from_ymd(2023, 1, 1);
    let operations = tinkoff
        .operations(&figi, OperationState::Unspecified, from.into(), to.into())
        .await?;

    println!("{:?}", operations);

    Ok(())
}

get portfolio

use tinkoff_invest::TinkoffInvest;

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let accounts = tinkoff.accounts().await?;

    let first_account = accounts.get(0).unwrap().clone();

    tinkoff.set_account(Some(first_account));

    let portfolio = tinkoff.portfolio().await?;

    println!("{:?}", portfolio);

    Ok(())
}

Streams

Market Data Stream

use tinkoff_invest::enums::{CandlestickInterval, MarketDataStreamData};
use tinkoff_invest::streams::MarketDataStreamBuilder;
use tinkoff_invest::types::Figi;
use tinkoff_invest::TinkoffInvest;

async fn market_data_handler(market_data: MarketDataStreamData) {
    println!("market data: {:?}", market_data);
}

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let tinkoff = TinkoffInvest::new(token.into()).await?;

    let market_data_stream_builder = MarketDataStreamBuilder::from(&tinkoff);
    let mut market_data_stream = market_data_stream_builder.build().await?;

    market_data_stream
        .subscribe_candlesticks(&[&Figi::from("BBG004730N88")], &CandlestickInterval::Min)
        .await?;

    let mut broadcast_receiver = market_data_stream.subscribe();

    tokio::spawn(async move {
        while let MarketDataStreamData::Candlestick(candlestick) = broadcast_receiver.recv().await.unwrap() {
            println!("{:?}", candlestick);
        }
    });

    market_data_stream.task.await?;

    Ok(())
}

Cached Market Instruments

example

use tinkoff_invest::{
    enums::{ClassCode, InstrumentType},
    types::{Figi, Ticker},
    CachedMarketInstruments, TinkoffInvest,
};

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let mut tinkoff = TinkoffInvest::new(token.into()).await?;

    let market_instruments = tinkoff
        .market_instruments(InstrumentType::Share)
        .await?;

    let cached_market_instruments = CachedMarketInstruments::from(market_instruments);

    // find by figi
    {
        let figi = Figi::from("BBG004730N88");
        let market_instrument = cached_market_instruments.by_figi(&figi).unwrap();
        println!("{:?}", market_instrument);
    }

    // find by class code and ticker
    {
        let class_code_ticker = (ClassCode::TQBR, Ticker::from("SBER"));
        let market_instrument = cached_market_instruments
            .by_class_code_and_ticker(&class_code_ticker)
            .unwrap();
        println!("{:?}", market_instrument);
    }

    // find by ticker
    {
        let ticker = Ticker::from("SBER");
        let market_instrument = cached_market_instruments.by_ticker(&ticker).unwrap();
        println!("{:?}", market_instrument);
    }

    Ok(())
}

Cached Orderbook

use std::sync::Arc;
use std::time::Duration;
use tinkoff_invest::cached::CachedOrderbooks;
use tinkoff_invest::enums::MarketDataStreamData;
use tinkoff_invest::streams::MarketDataStreamBuilder;
use tinkoff_invest::types::Uid;
use tinkoff_invest::TinkoffInvest;
use tokio::sync::RwLock;

#[tokio::main()]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = "...";

    let tinkoff = TinkoffInvest::new(token.into()).await?;

    let market_data_stream_builder = MarketDataStreamBuilder::from(&tinkoff);
    let mut market_data_stream = market_data_stream_builder.build().await?;

    market_data_stream
        .subscribe_orderbook(&[Uid::from("e6123145-9665-43e0-8413-cd61b8aa9b13")], 10)
        .await?;

    let mut broadcast_receiver = market_data_stream.subscribe();

    let cached_orderbooks = Arc::new(RwLock::new(CachedOrderbooks::new()));

    let write_thread_cached_orderbooks = cached_orderbooks.clone();
    tokio::spawn(async move {
        loop {
            match broadcast_receiver.recv().await {
                Ok(MarketDataStreamData::Orderbook(orderbook)) => {
                    write_thread_cached_orderbooks.write().await.add(orderbook);
                }
                Err(error) => {
                    println!("error: {}", error);
                }
                _ => {}
            }
        }
    });

    let read_thread_cached_orderbooks = cached_orderbooks.clone();
    tokio::spawn(async move {
        loop {
            tokio::time::sleep(Duration::from_secs(5)).await;
            let lock_guard = read_thread_cached_orderbooks.read().await;
            let orderbook = lock_guard.get(&Uid::from("e6123145-9665-43e0-8413-cd61b8aa9b13"));
            println!("orderbook: {:?}", orderbook);
        }
    }).await?;

    Ok(())
}

Dependencies

~14–24MB
~425K SLoC