Skip to content

Commit

Permalink
Rename Tinkoff -> T-Bank everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
KonishchevDmitry committed Jan 12, 2025
1 parent 35b3836 commit bd520d0
Show file tree
Hide file tree
Showing 31 changed files with 97 additions and 95 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
--skip broker_statement::ib::tests::parse_real
--skip broker_statement::open::tests::parse_real
--skip broker_statement::sber::tests::parse_real
--skip broker_statement::tinkoff::tests::parse_real
--skip broker_statement::tinkoff::foreign_income::tests::parse_real
--skip broker_statement::tbank::tests::parse_real
--skip broker_statement::tbank::foreign_income::tests::parse_real
--skip tax_statement::statement::parser::tests::parse_real
--skip telemetry::tests::telemetry
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "testdata"]
path = testdata
url = git@konishchev.ru:investments-testdata.git
[submodule "src/quotes/tinkoff/api"]
path = src/quotes/tinkoff/api
[submodule "src/quotes/tbank/api"]
path = src/quotes/tbank/api
url = git@github.com:Tinkoff/investAPI.git
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"search.exclude": {
"/src/quotes/tinkoff/api/src/docs": true,
"/src/quotes/tbank/api/src/docs": true,
"/testdata/bcs/*/*.sign": true,
"/testdata/rt_*": true,
},
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ license = "GPL-3.0+"
readme = "README.md"

edition = "2021"
exclude = ["/src/quotes/tinkoff/api", "/testdata"]
exclude = ["/src/quotes/tbank/api", "/testdata"]

[[bin]]
name = "investments"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Helps you with managing your investments:
* **Analysis:** calculates average rate of return from cash investments by comparing portfolio performance to performance of a bank deposit in USD and RUB currency with exactly the same investments and monthly capitalization. Considers taxes, commissions, dividends, tax deductions and optionally inflation when calculates portfolio performance.
* **Bank deposits control:** view opened bank deposits all in one place and get notified about upcoming deposit closures.

Targeted for Russian investors who use [Firstrade](https://www.firstrade.com/), [Interactive Brokers](https://interactivebrokers.com/), [БКС](https://broker.ru/), [Сбер](https://sberbank.ru/) or [Тинькофф](https://www.tinkoff.ru/).
Targeted for Russian investors who use [Firstrade](https://www.firstrade.com/), [Interactive Brokers](https://interactivebrokers.com/), [БКС](https://broker.ru/), [Сбер](https://sberbank.ru/) or [Т-Банк](https://www.tbank.ru/).

# Installation

Expand All @@ -30,7 +30,7 @@ For now the following brokers are supported:
* Interactive Brokers ([details](https://github.com/KonishchevDmitry/investments/blob/master/docs/brokers.md#interactive-brokers))
* БКС ([details](https://github.com/KonishchevDmitry/investments/blob/master/docs/brokers.md#bcs))
* Сбер ([details](https://github.com/KonishchevDmitry/investments/blob/master/docs/brokers.md#sber))
* Тинькофф ([details](https://github.com/KonishchevDmitry/investments/blob/master/docs/brokers.md#tinkoff))
* Т-Банк ([details](https://github.com/KonishchevDmitry/investments/blob/master/docs/brokers.md#tbank))

Investments keeps some data in local database located at `~/.investments/db.sqlite` and supports a number of commands which can be grouped as:
* Analyse commands ([analyse](#analyse), [cash-flow](docs/taxes.md#cash-flow), [metrics](#metrics),
Expand Down
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::Path;
use std::process;

fn generate() -> Result<(), Box<dyn Error + Send + Sync>> {
let base_dir = Path::new("src/quotes/tinkoff");
let base_dir = Path::new("src/quotes/tbank");
let protos_dir = base_dir.join("api/src/docs/contracts");

let protos = [
Expand Down
8 changes: 4 additions & 4 deletions docs/brokers.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ Dividend records in the statement are identified by some broker-specific instrum
The program expects broker statements in `*.html` format. For now only basic statements are supported since I don't have more examples of how various situations look like in them.


<a name="tinkoff"></a>
## Тинькофф
<a name="tbank"></a>
## Т-Банк

The program expects broker statements in `*.xlsx` format.

Tinkoff broker statements don't contain any information about corporate actions, so stock splits must be specified manually via `corporate_actions` configuration option.
T-Bank broker statements don't contain any information about corporate actions, so stock splits must be specified manually via `corporate_actions` configuration option.

<a name="tinkoff-foreign-income"></a>
### Foreign dividend income until 2024

Until 2024, in which Tinkoff became tax agent for foreign dividend income, the broker statements didn't contain dividend and tax withheld amounts for dividends from non-Russian issuers - only result amount which has been paid. This information is provided in a separate foreign income statement (Справка о доходах за пределами РФ) which is only available as *.pdf (very unsuitable for parsing) from your account page. But you can ask support for *.xlsx version of it and place it to the broker statements directory. The program will find it and merge its information with broker statement.
Until 2024, in which T-Bank became tax agent for foreign dividend income, the broker statements didn't contain dividend and tax withheld amounts for dividends from non-Russian issuers - only result amount which has been paid. This information is provided in a separate foreign income statement (Справка о доходах за пределами РФ) which is only available as *.pdf (very unsuitable for parsing) from your account page. But you can ask support for *.xlsx version of it and place it to the broker statements directory. The program will find it and merge its information with broker statement.
10 changes: 5 additions & 5 deletions docs/config-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ portfolios:
# Received tax deductions can be specified here and will be taken into account during portfolio performance analysis
2024.08.25: 52000

- name: tinkoff
broker: tinkoff
- name: tbank
broker: tbank
plan: Инвестор
statements: ~/Brokerage/Тинькофф/Отчеты Брокера
statements: ~/Brokerage/Т-Банк/Отчеты Брокера

# Configures the account as account to which long-term ownership tax exemption can be applied
tax_exemptions: [long-term-ownership]

# Tinkoff doesn't provide any information about corporate actions, so we have to specify them manually
# T-Bank doesn't provide any information about corporate actions, so we have to specify them manually
#corporate_actions:
# - {date: 2020.10.27, symbol: NEE, type: stock-split, ratio: 4:1}
# - {date: 2022.06.27, symbol: FXRB, type: delisting, quantity: 12460} # FinEx FXRB fund lost all its assets and has been closed
Expand Down Expand Up @@ -172,7 +172,7 @@ brokers:
RUB: {fixed_amount: 0}
USD: {fixed_amount: 0}

tinkoff:
tbank:
# Sandbox token from https://tinkoff.github.io/investAPI/token/
#api_token: secret

Expand Down
2 changes: 1 addition & 1 deletion docs/quotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The program needs stock and forex quotes for its work. It's actually a real prob

At this time investments uses [FCS API](https://fcsapi.com/) and [Finnhub](https://finnhub.io/), so you have to register, obtain API tokens and specify them in configuration file (see [example config](config-example.yaml)).

If you are client of [Tinkoff broker](https://www.tinkoff.ru/invest/), it's also highly recommended to obtain [Tinkoff Invest API sandbox token](https://tinkoff.github.io/investAPI/token/) and specify it in the config: Tinkoff has a brilliant API with very high rate limits. When token is specified in config, investments uses Tinkoff API for currency and SPB Exchange quotes + also falls back to Tinkoff SPB/OTC quotes for other exchanges for which it doesn't have quotes provider yet (LSE and HKEX for example).
If you are client of [T-Bank broker](https://www.tbank.ru/invest/), it's also highly recommended to obtain [T-Bank Invest API sandbox token](https://tinkoff.github.io/investAPI/token/) and specify it in the config: T-Bank has a brilliant API with very high rate limits. When token is specified in config, investments uses T-Bank API for currency and SPB Exchange quotes + also falls back to T-Bank SPB/OTC quotes for other exchanges for which it doesn't have quotes provider yet (LSE and HKEX for example).

## Custom quotes provider

Expand Down
2 changes: 1 addition & 1 deletion src/broker_statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod firstrade;
mod ib;
mod open;
mod sber;
mod tinkoff;
mod tbank;

use std::cmp::Ordering;
use std::collections::{HashMap, BTreeMap, BTreeSet, hash_map::Entry};
Expand Down
4 changes: 2 additions & 2 deletions src/broker_statement/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::core::{GenericResult, EmptyResult};
use crate::brokers::Broker;
use crate::taxes::TaxRemapping;

use super::{bcs, firstrade, ib, open, sber, tinkoff};
use super::{bcs, firstrade, ib, open, sber, tbank};
use super::PartialBrokerStatement;

bitflags! {
Expand Down Expand Up @@ -41,7 +41,7 @@ pub fn read(
Broker::InteractiveBrokers => ib::StatementReader::new(tax_remapping.take().unwrap(), strictness),
Broker::Open => open::StatementReader::new(),
Broker::Sber => sber::StatementReader::new(),
Broker::Tinkoff => tinkoff::StatementReader::new(),
Broker::Tbank => tbank::StatementReader::new(),
}?;

let mut file_names = preprocess_statement_directory(statement_dir_path, statement_reader.as_mut())
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl ForeignIncomeRow {
}
}

// Until 2024, in which Tinkoff became tax agent for foreign dividend income, the broker statements didn't contain
// Until 2024, in which T-Bank became tax agent for foreign dividend income, the broker statements didn't contain
// dividend and tax withheld amounts for dividends from non-Russian issuers - only result amount which has been paid.
//
// So until 2024 we had to parse foreign income statements to get this information from them. Starting from 2024 we
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Tinkoff statement T+N specific:
T-Bank statement T+N specific:
All trades are split into two categories: executed and not executed (yet). If trade is not executed
yet, it's listed in not executed table in current statement and then will be listed in executed
Expand Down Expand Up @@ -322,7 +322,7 @@ mod tests {
_ => name.to_owned(),
};

let broker = Broker::Tinkoff.get_info(&Config::mock(), None).unwrap();
let broker = Broker::Tbank.get_info(&Config::mock(), None).unwrap();
let config = Config::load(&format!("testdata/configs/{}/config.yaml", namespace)).unwrap();
let portfolio = config.get_portfolio(&portfolio_name).unwrap();

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
29 changes: 15 additions & 14 deletions src/brokers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub enum Broker {
InteractiveBrokers,
Open,
Sber,
Tinkoff,
Tbank,
}

impl Broker {
Expand All @@ -44,7 +44,7 @@ impl Broker {

config: config,
commission_spec: self.get_commission_spec(plan)?,
allow_future_fees: matches!(self, Broker::Tinkoff),
allow_future_fees: matches!(self, Broker::Tbank),
fractional_shares_trading: matches!(self, Broker::InteractiveBrokers),
statements_merging_strategy: statements_merging_strategy,
})
Expand All @@ -57,7 +57,7 @@ impl Broker {
Broker::InteractiveBrokers => "interactive-brokers",
Broker::Open => "open",
Broker::Sber => "sber",
Broker::Tinkoff => "tinkoff",
Broker::Tbank => "tbank",
}
}

Expand All @@ -68,7 +68,7 @@ impl Broker {
Broker::InteractiveBrokers => "Interactive Brokers LLC",
Broker::Open => "АО «Открытие Брокер»",
Broker::Sber => "ПАО «Сбербанк»",
Broker::Tinkoff => "АО «Тинькофф Банк»",
Broker::Tbank => "АО «ТБанк»",
}
}

Expand All @@ -79,13 +79,13 @@ impl Broker {
Broker::InteractiveBrokers => "Interactive Brokers",
Broker::Open => "Открытие",
Broker::Sber => "Сбер",
Broker::Tinkoff => "Тинькофф",
Broker::Tbank => "Т‑Банк",
}
}

pub fn jurisdiction(self) -> Jurisdiction {
match self {
Broker::Bcs | Broker::Open | Broker::Sber | Broker::Tinkoff => Jurisdiction::Russia,
Broker::Bcs | Broker::Open | Broker::Sber | Broker::Tbank => Jurisdiction::Russia,
Broker::Firstrade | Broker::InteractiveBrokers => Jurisdiction::Usa,
}
}
Expand All @@ -97,7 +97,7 @@ impl Broker {
Broker::InteractiveBrokers => config.interactive_brokers.as_ref(),
Broker::Open => config.open_broker.as_ref(),
Broker::Sber => config.sber.as_ref(),
Broker::Tinkoff => config.tinkoff.as_ref().and_then(|tinkoff| tinkoff.broker.as_ref()),
Broker::Tbank => config.tbank.as_ref().and_then(|tbank| tbank.broker.as_ref()),
}
}

Expand Down Expand Up @@ -129,10 +129,10 @@ impl Broker {
"Самостоятельный" => plans::sber::manual as PlanFn,
}),

Broker::Tinkoff => (plans::tinkoff::investor, btreemap!{
"Инвестор" => plans::tinkoff::investor as PlanFn,
"Трейдер" => plans::tinkoff::trader as PlanFn,
"Премиум" => plans::tinkoff::premium as PlanFn,
Broker::Tbank => (plans::tbank::investor, btreemap!{
"Инвестор" => plans::tbank::investor as PlanFn,
"Трейдер" => plans::tbank::trader as PlanFn,
"Премиум" => plans::tbank::premium as PlanFn,
}),
};

Expand Down Expand Up @@ -160,10 +160,11 @@ impl<'de> Deserialize<'de> for Broker {
"interactive-brokers" => Broker::InteractiveBrokers,
"open-broker" => Broker::Open,
"sber" => Broker::Sber,
"tinkoff" => Broker::Tinkoff,
"tbank" => Broker::Tbank,
"tinkoff" => Broker::Tbank,

_ => return Err(D::Error::unknown_variant(&value, &[
"bcs", "firstrade", "interactive-brokers", "open-broker", "sber", "tinkoff",
"bcs", "firstrade", "interactive-brokers", "open-broker", "sber", "tbank",
])),
})
}
Expand Down Expand Up @@ -200,7 +201,7 @@ impl BrokerInfo {
pub fn exchanges(&self) -> Vec<Exchange> {
match self.type_ {
Broker::Bcs | Broker::Open | Broker::Sber => vec![Exchange::Moex, Exchange::Spb],
Broker::Tinkoff => vec![Exchange::Moex, Exchange::Spb, Exchange::Otc],
Broker::Tbank => vec![Exchange::Moex, Exchange::Spb, Exchange::Otc],
Broker::Firstrade => vec![Exchange::Us],
Broker::InteractiveBrokers => vec![Exchange::Us, Exchange::Other],
}
Expand Down
2 changes: 1 addition & 1 deletion src/brokers/plans/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ pub mod firstrade;
pub mod ib;
pub mod open;
pub mod sber;
pub mod tinkoff;
pub mod tbank;
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn investor() -> CommissionSpec {
}

// Please note:
// We don't support Tinkoff volume tiers: actual commission depends on the order of trades which is
// We don't support T-Bank volume tiers: actual commission depends on the order of trades which is
// inappropriate for our purposes.
pub fn trader() -> CommissionSpec {
CommissionSpecBuilder::new("RUB")
Expand Down
9 changes: 5 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::quotes::QuotesConfig;
use crate::quotes::alphavantage::AlphaVantageConfig;
use crate::quotes::fcsapi::FcsApiConfig;
use crate::quotes::finnhub::FinnhubConfig;
use crate::quotes::tinkoff::TinkoffApiConfig;
use crate::quotes::tbank::TbankApiConfig;
use crate::quotes::twelvedata::TwelveDataConfig;
use crate::taxes::{self, TaxConfig, TaxExemption, TaxPaymentDay, TaxPaymentDaySpec, TaxRemapping};
use crate::telemetry::TelemetryConfig;
Expand Down Expand Up @@ -377,16 +377,17 @@ pub struct BrokersConfig {
pub interactive_brokers: Option<BrokerConfig>,
pub open_broker: Option<BrokerConfig>,
pub sber: Option<BrokerConfig>,
pub tinkoff: Option<TinkoffConfig>,
#[serde(alias = "tinkoff")]
pub tbank: Option<TbankConfig>,
}

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TinkoffConfig {
pub struct TbankConfig {
#[serde(flatten)]
pub broker: Option<BrokerConfig>,
#[serde(flatten)]
pub api: Option<TinkoffApiConfig>,
pub api: Option<TbankApiConfig>,
}

#[derive(Deserialize, Default, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion src/formats/xls/sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl SheetReader {
pub trait SheetParser {
fn sheet_name(&self) -> &str;

// In the beginning of 2024 year Tinkoff statements became broken: empty tables started to lose random columns.
// In the beginning of 2024 year T-Bank statements became broken: empty tables started to lose random columns.
// This property can help to workaround such temporary problems.
fn parse_empty_tables(&self) -> bool {
true
Expand Down
4 changes: 2 additions & 2 deletions src/instruments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl InstrumentInternalIds {

// Please note that we don't guarantee that symbol will actually be symbol (ticker). Broker statement may have no symbol
// information for an instrument. Some brokers just don't provide it (BCS) or it may be unavailable for some particular
// instruments (OTC stocks in Tinkoff). In this case the symbol will be actually ISIN and we rely on symbol remapping in
// instruments (OTC stocks in T-Bank). In this case the symbol will be actually ISIN and we rely on symbol remapping in
// such cases.
pub struct InstrumentInfo {
instruments: HashMap<String, Instrument>,
Expand Down Expand Up @@ -193,7 +193,7 @@ impl InstrumentInfo {
'symbol_loop: for symbol in self.instruments.keys() {
// The case:
//
// Finex ETF were bought on MOEX exchange, but then have been delisted due to sanctions. Old Tinkoff
// Finex ETF were bought on MOEX exchange, but then have been delisted due to sanctions. Old T-Bank
// statements contain symbol <-> ISIN mapping, but new ones have only ISIN (since it's considered as
// an OTC stock).

Expand Down
Loading

0 comments on commit bd520d0

Please sign in to comment.