cbrapi 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cbrapi-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.3
2
+ Name: cbrapi
3
+ Version: 0.1.0
4
+ Summary: Python interface for Central Bank of Russia (CBR) API
5
+ Author: AAARRRT
6
+ Author-email: artiomsalazov@gmail.com
7
+ Requires-Python: >=3.10,<4.0.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: lxml
14
+ Requires-Dist: pandas (>=2.3.2,<3.0.0)
15
+ Requires-Dist: requests
16
+ Requires-Dist: suds-py3
17
+ Description-Content-Type: text/markdown
18
+
19
+
20
+ [![Python](https://img.shields.io/badge/python-v3-brightgreen.svg)](https://www.python.org/)
21
+ [![PyPI Latest Release](https://img.shields.io/pypi/v/okama.svg)](https://pypi.org/project/okama/)
22
+ [![License](https://img.shields.io/pypi/l/okama.svg)](https://opensource.org/licenses/MIT)
23
+ [![Downloads](https://static.pepy.tech/badge/cbr-api-client)](https://pepy.tech/project/cbr-api)
24
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
25
+
26
+ # CBRAPI
27
+
28
+ `cbrapi` is a Python client for the Central Bank of Russia's web services.
29
+
30
+ ## Table of contents
31
+
32
+ - [CBR-API main features](#cbr-api-main-features)
33
+ - [Core Functions](#core-functions)
34
+ - [CURRENCY](#currency)
35
+ - [METALS](#metals)
36
+ - [RATES](#rates)
37
+ - [RESERVES](#reserves)
38
+ - [RUONIA](#ruonia)
39
+ - [Getting started](#getting-started)
40
+ - [License](#license)
41
+
42
+ ## CBRAPI main features
43
+ This client provides structured access to the following key data categories from the CBR:
44
+ - CURRENCY: Official exchange rates of foreign currencies against the Russian Ruble.
45
+ - METALS: Official prices of precious metals.
46
+ - RATES: Key interest rates and interbank lending rates.
47
+ - RESERVES: Data on international reserves and foreign currency liquidity.
48
+ - RUONIA: The Russian Overnight Index Average and related benchmark rates.
49
+
50
+ ## Core Functions
51
+
52
+ ### CURRENCY
53
+
54
+ #### Get a list of available currencies
55
+ Returns a list of all available currency tickers supported by the API.
56
+ `get_currencies_list()`
57
+
58
+ #### Get an internal CBR currency code for a ticker
59
+ Retrieves the internal CBR currency code for a given currency ticker.
60
+ `get_currency_code(ticker: str)`
61
+
62
+ #### Get currency rate historical data
63
+ Fetches historical exchange rate data for a specified currency and date range.
64
+ `get_time_series(symbol: str, first_date: str, last_date: str, period: str = 'D')`
65
+
66
+ ### METALS
67
+
68
+ #### Get precious metals prices time series
69
+ Provides historical prices for precious metals (Gold, Silver, Platinum, Palladium).
70
+ `get_metals_prices(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
71
+
72
+ ### RATES
73
+
74
+ IBOR: Interbank Offered Rate.
75
+
76
+ #### Get the key rate time series
77
+ Retrieves the historical key rate set by the Central Bank of Russia.
78
+ `get_key_rate(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
79
+
80
+ #### Get Interbank Offered Rate and related interbank rates
81
+ Fetches the historical Interbank Offered Rate and related interbank rates.
82
+ `get_ibor(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'M')`
83
+
84
+ ### RESERVES
85
+
86
+ MRRF: International Reserves and Foreign Currency Liquidity.
87
+
88
+ #### Get International Reserves and Foreign Currency Liquidity data
89
+ Provides time series data for International Reserves and Foreign Currency Liquidity.
90
+ `get_mrrf(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'M')`
91
+
92
+ ### RUONIA
93
+
94
+ RUONIA: Russian Overnight Index Average.
95
+ ROISfix: Russian Overnight Index Swap Fixing.
96
+
97
+ #### Get RUONIA time series data
98
+ Retrieves RUONIA time series data for a specific symbol.
99
+ `get_ruonia_ts(symbol: str, first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
100
+
101
+ #### Get RUONIA index and averages time series
102
+ Fetches the historical RUONIA index and averages.
103
+ `get_ruonia_index(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
104
+
105
+ #### Get RUONIA overnight value time series
106
+ Provides the historical RUONIA overnight value.
107
+ `get_ruonia_overnight(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
108
+
109
+ #### Get ROISfix time series
110
+ Retrieves the historical ROISfix time series data.
111
+ `get_roisfix(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
112
+
113
+ ## Installation
114
+
115
+ ```bash
116
+ pip install cbrapi
117
+ ```
118
+
119
+ The latest development version can be installed directly from GitHub:
120
+
121
+ ```bash
122
+ git clone https://github.com/mbk-dev/cbrapi.git
123
+ cd cbrapi
124
+ poetry install
125
+ ```
126
+
127
+ ## Getting started
128
+
129
+
130
+ ### 1. Get USD/RUB exchange rate with historical data
131
+
132
+ ```python
133
+ import cbrapi as cbr
134
+
135
+ usd_rub = cbr.get_currency_rate('USDRUB.CBR', '2024-01-01', '2024-12-31')
136
+ print(usd_rub)
137
+ ```
138
+ ![](../images/images/readme1.jpg?raw=true)
139
+
140
+
141
+ ### 2. Monitor Central Bank's key rate monthly changes
142
+
143
+ ```python
144
+ key_rate = cbr.get_key_rate('2020-01-01', '2024-12-31', period='M')
145
+ print(key_rate)
146
+ ```
147
+ ![](../images/images/readme2.jpg?raw=true)
148
+
149
+
150
+ ### 3. Track precious metals market trends
151
+ ```python
152
+ metals = cbr.get_metals_prices('2024-01-01', '2025-01-31')
153
+ print(metals)
154
+ ```
155
+ ![](../images/images/readme3.jpg?raw=true)
156
+
157
+
158
+ ### 4. Analyze international reserves data
159
+ ```python
160
+ reserves = cbr.get_mrrf('2023-01-01', '2024-12-31')
161
+ print(reserves)
162
+ ```
163
+ ![](../images/images/readme4.jpg?raw=true)
164
+
165
+
166
+ ## License
167
+
168
+ MIT
169
+
cbrapi-0.1.0/README.md ADDED
@@ -0,0 +1,150 @@
1
+
2
+ [![Python](https://img.shields.io/badge/python-v3-brightgreen.svg)](https://www.python.org/)
3
+ [![PyPI Latest Release](https://img.shields.io/pypi/v/okama.svg)](https://pypi.org/project/okama/)
4
+ [![License](https://img.shields.io/pypi/l/okama.svg)](https://opensource.org/licenses/MIT)
5
+ [![Downloads](https://static.pepy.tech/badge/cbr-api-client)](https://pepy.tech/project/cbr-api)
6
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
7
+
8
+ # CBRAPI
9
+
10
+ `cbrapi` is a Python client for the Central Bank of Russia's web services.
11
+
12
+ ## Table of contents
13
+
14
+ - [CBR-API main features](#cbr-api-main-features)
15
+ - [Core Functions](#core-functions)
16
+ - [CURRENCY](#currency)
17
+ - [METALS](#metals)
18
+ - [RATES](#rates)
19
+ - [RESERVES](#reserves)
20
+ - [RUONIA](#ruonia)
21
+ - [Getting started](#getting-started)
22
+ - [License](#license)
23
+
24
+ ## CBRAPI main features
25
+ This client provides structured access to the following key data categories from the CBR:
26
+ - CURRENCY: Official exchange rates of foreign currencies against the Russian Ruble.
27
+ - METALS: Official prices of precious metals.
28
+ - RATES: Key interest rates and interbank lending rates.
29
+ - RESERVES: Data on international reserves and foreign currency liquidity.
30
+ - RUONIA: The Russian Overnight Index Average and related benchmark rates.
31
+
32
+ ## Core Functions
33
+
34
+ ### CURRENCY
35
+
36
+ #### Get a list of available currencies
37
+ Returns a list of all available currency tickers supported by the API.
38
+ `get_currencies_list()`
39
+
40
+ #### Get an internal CBR currency code for a ticker
41
+ Retrieves the internal CBR currency code for a given currency ticker.
42
+ `get_currency_code(ticker: str)`
43
+
44
+ #### Get currency rate historical data
45
+ Fetches historical exchange rate data for a specified currency and date range.
46
+ `get_time_series(symbol: str, first_date: str, last_date: str, period: str = 'D')`
47
+
48
+ ### METALS
49
+
50
+ #### Get precious metals prices time series
51
+ Provides historical prices for precious metals (Gold, Silver, Platinum, Palladium).
52
+ `get_metals_prices(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
53
+
54
+ ### RATES
55
+
56
+ IBOR: Interbank Offered Rate.
57
+
58
+ #### Get the key rate time series
59
+ Retrieves the historical key rate set by the Central Bank of Russia.
60
+ `get_key_rate(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
61
+
62
+ #### Get Interbank Offered Rate and related interbank rates
63
+ Fetches the historical Interbank Offered Rate and related interbank rates.
64
+ `get_ibor(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'M')`
65
+
66
+ ### RESERVES
67
+
68
+ MRRF: International Reserves and Foreign Currency Liquidity.
69
+
70
+ #### Get International Reserves and Foreign Currency Liquidity data
71
+ Provides time series data for International Reserves and Foreign Currency Liquidity.
72
+ `get_mrrf(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'M')`
73
+
74
+ ### RUONIA
75
+
76
+ RUONIA: Russian Overnight Index Average.
77
+ ROISfix: Russian Overnight Index Swap Fixing.
78
+
79
+ #### Get RUONIA time series data
80
+ Retrieves RUONIA time series data for a specific symbol.
81
+ `get_ruonia_ts(symbol: str, first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
82
+
83
+ #### Get RUONIA index and averages time series
84
+ Fetches the historical RUONIA index and averages.
85
+ `get_ruonia_index(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
86
+
87
+ #### Get RUONIA overnight value time series
88
+ Provides the historical RUONIA overnight value.
89
+ `get_ruonia_overnight(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
90
+
91
+ #### Get ROISfix time series
92
+ Retrieves the historical ROISfix time series data.
93
+ `get_roisfix(first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = 'D')`
94
+
95
+ ## Installation
96
+
97
+ ```bash
98
+ pip install cbrapi
99
+ ```
100
+
101
+ The latest development version can be installed directly from GitHub:
102
+
103
+ ```bash
104
+ git clone https://github.com/mbk-dev/cbrapi.git
105
+ cd cbrapi
106
+ poetry install
107
+ ```
108
+
109
+ ## Getting started
110
+
111
+
112
+ ### 1. Get USD/RUB exchange rate with historical data
113
+
114
+ ```python
115
+ import cbrapi as cbr
116
+
117
+ usd_rub = cbr.get_currency_rate('USDRUB.CBR', '2024-01-01', '2024-12-31')
118
+ print(usd_rub)
119
+ ```
120
+ ![](../images/images/readme1.jpg?raw=true)
121
+
122
+
123
+ ### 2. Monitor Central Bank's key rate monthly changes
124
+
125
+ ```python
126
+ key_rate = cbr.get_key_rate('2020-01-01', '2024-12-31', period='M')
127
+ print(key_rate)
128
+ ```
129
+ ![](../images/images/readme2.jpg?raw=true)
130
+
131
+
132
+ ### 3. Track precious metals market trends
133
+ ```python
134
+ metals = cbr.get_metals_prices('2024-01-01', '2025-01-31')
135
+ print(metals)
136
+ ```
137
+ ![](../images/images/readme3.jpg?raw=true)
138
+
139
+
140
+ ### 4. Analyze international reserves data
141
+ ```python
142
+ reserves = cbr.get_mrrf('2023-01-01', '2024-12-31')
143
+ print(reserves)
144
+ ```
145
+ ![](../images/images/readme4.jpg?raw=true)
146
+
147
+
148
+ ## License
149
+
150
+ MIT
@@ -0,0 +1,23 @@
1
+ from importlib.metadata import version
2
+
3
+
4
+ from cbrapi.cbr_settings import make_cbr_client
5
+ from cbrapi.currency import get_currencies_list, get_currency_code, get_time_series
6
+ from cbrapi.helpers import (
7
+ pad_missing_periods,
8
+ calculate_inverse_rate,
9
+ normalize_data,
10
+ guess_date,
11
+ )
12
+ from cbrapi.ruonia import (
13
+ get_ruonia_ts,
14
+ get_ruonia_index,
15
+ get_ruonia_overnight,
16
+ get_roisfix,
17
+ )
18
+ from cbrapi.rates import get_key_rate, get_ibor
19
+ from cbrapi.metals import get_metals_prices
20
+ from cbrapi.reserves import get_mrrf
21
+
22
+
23
+ # __version__ = version("cbr")
@@ -0,0 +1,15 @@
1
+ from suds.client import Client
2
+ from suds.xsd.doctor import Import, ImportDoctor
3
+
4
+
5
+ def make_cbr_client():
6
+ global cbr_client
7
+ imp = Import("http://www.w3.org/2001/XMLSchema") # the schema to import
8
+ imp.filter.add("http://web.cbr.ru/") # the schema to import into
9
+ d = ImportDoctor(imp)
10
+ return Client(
11
+ "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?wsdl",
12
+ doctor=d,
13
+ retxml=True,
14
+ headers={"User-Agent": "Mozilla"},
15
+ )
@@ -0,0 +1,177 @@
1
+ import re
2
+ from datetime import datetime, date
3
+ from typing import Optional
4
+
5
+ import pandas as pd
6
+
7
+ from cbrapi.cbr_settings import make_cbr_client
8
+ from cbrapi.helpers import (
9
+ normalize_data,
10
+ guess_date,
11
+ pad_missing_periods,
12
+ calculate_inverse_rate,
13
+ )
14
+
15
+
16
+ today = date.today()
17
+
18
+
19
+ def get_currencies_list() -> pd.DataFrame:
20
+ """
21
+ Get a list of available currencies from CBR.
22
+
23
+ Returns
24
+ -------
25
+ pd.DataFrame
26
+ Combined dataframe with all available currencies for daily and monthly frequencies.
27
+ Contains currency codes, character codes, names, and metadata.
28
+
29
+ Notes
30
+ -----
31
+ The function retrieves two separate lists:
32
+ - Currencies with DAILY time series data
33
+ - Currencies with MONTHLY time series data
34
+ Returns a combined dataframe with all available currencies.
35
+
36
+ Examples
37
+ --------
38
+ >>> get_currencies_list()
39
+ """
40
+ cbr_client = make_cbr_client()
41
+ # get currency table with DAILY time series
42
+ currencies_daily_xml = cbr_client.service.EnumValutesXML(False)
43
+ df_daily = pd.read_xml(currencies_daily_xml, xpath="//EnumValutes")
44
+
45
+ # get currency table with MONTHLY time series
46
+ currencies_monthly_xml = cbr_client.service.EnumValutesXML(True)
47
+ df_monthly = pd.read_xml(currencies_monthly_xml, xpath="//EnumValutes")
48
+ return pd.concat([df_daily, df_monthly], axis=0, join="outer", copy="false")
49
+
50
+
51
+ def get_currency_code(ticker: str) -> str:
52
+ """
53
+ Return an internal CBR currency code for a ticker.
54
+
55
+ Parameters
56
+ ----------
57
+ ticker : str
58
+ Currency ticker in format 'CCY1CCY2.CBR' (e.g., 'USDRUB.CBR')
59
+
60
+ Returns
61
+ -------
62
+ str
63
+ Internal CBR currency code (e.g., 'R01235')
64
+
65
+ Raises
66
+ ------
67
+ ValueError
68
+ If the currency ticker is not found in the CBR database.
69
+
70
+ Notes
71
+ -----
72
+ Handles cases where multiple currency codes might exist for the same ticker
73
+ by selecting the first available option.
74
+
75
+ Examples
76
+ --------
77
+ >>> get_currency_code('USDRUB.CBR')
78
+ 'R01235'
79
+ """
80
+ cbr_symbol = ticker[:3]
81
+ currencies_list = get_currencies_list()
82
+ # Some tickers has 2 Vcode in CBR database. ILS - "Израильский шекель" and "Новый израильский шекель"
83
+ # First row is taken with .iloc
84
+ row = (
85
+ currencies_list[currencies_list["VcharCode"] == cbr_symbol].iloc[0, :].squeeze()
86
+ )
87
+ try:
88
+ code = row.loc["Vcode"]
89
+ except KeyError as e:
90
+ raise ValueError(f"There is no {ticker} in CBR database.") from e
91
+ return code
92
+
93
+
94
+ def get_time_series(
95
+ symbol: str, first_date: str, last_date: str, period: str = "D"
96
+ ) -> pd.Series:
97
+ """
98
+ Get currency rate historical data from CBR.
99
+
100
+ Parameters
101
+ ----------
102
+ symbol : str
103
+ Currency pair symbol in format 'CCY1CCY2.CBR' (e.g., 'USDRUB.CBR')
104
+ first_date : str
105
+ Start date in format 'YYYY-MM-DD' or 'YYYY-MM'
106
+ last_date : str
107
+ End date in format 'YYYY-MM-DD' or 'YYYY-MM'
108
+ period : {'D', 'M'}, default 'D'
109
+ Data frequency: 'D' for daily, 'M' for monthly
110
+
111
+ Returns
112
+ -------
113
+ pd.Series
114
+ Time series of currency exchange rates with datetime index.
115
+
116
+ Raises
117
+ ------
118
+ ValueError
119
+ If the CBR data format has changed unexpectedly.
120
+ If date format is invalid.
121
+ If currency symbol is not found.
122
+
123
+ Notes
124
+ -----
125
+ - Supports both direct and inverse rate calculations
126
+ - Handles data normalization and missing period padding
127
+ - Performs resampling for different frequencies
128
+ - Some tickers may return empty data if not available
129
+
130
+ Examples
131
+ --------
132
+ >>> get_time_series('USDRUB.CBR', '2023-01-01', '2023-12-31', 'D')
133
+ >>> get_time_series('EURUSD.CBR', '2023-01', '2023-12', 'M')
134
+ """
135
+ try:
136
+ data1 = datetime.strptime(first_date, "%Y-%m-%d")
137
+ data2 = datetime.strptime(last_date, "%Y-%m-%d")
138
+ except ValueError:
139
+ data1 = datetime.strptime(first_date, "%Y-%m")
140
+ data2 = datetime.strptime(last_date, "%Y-%m")
141
+ symbol = symbol.upper()
142
+ if re.match("RUB", symbol):
143
+ foreign_ccy = re.search(r"^RUB(.*).CBR$", symbol)[1]
144
+ query_symbol = foreign_ccy + "RUB.CBR"
145
+ method = "inverse"
146
+ else:
147
+ query_symbol = symbol
148
+ method = "direct"
149
+ code = get_currency_code(query_symbol)
150
+ cbr_client = make_cbr_client()
151
+ rate_xml = cbr_client.service.GetCursDynamic(data1, data2, code)
152
+ try:
153
+ df = pd.read_xml(rate_xml, xpath="//ValuteCursDynamic")
154
+ except ValueError:
155
+ return pd.Series()
156
+ cbr_cols1 = {"rowOrder", "id", "Vnom", "Vcode", "CursDate", "Vcurs"}
157
+ cbr_cols2 = cbr_cols1.union({"VunitRate"})
158
+ if set(df.columns) not in [cbr_cols1, cbr_cols2]:
159
+ raise ValueError(
160
+ "CBR data has different columns. Probably data format is changed."
161
+ )
162
+ df.drop(columns=["id", "rowOrder", "Vcode"], inplace=True)
163
+ if "VunitRate" in list(df.columns):
164
+ df.drop(columns=["VunitRate"], inplace=True)
165
+ df["Vcurs"] /= df["Vnom"]
166
+ df.drop(columns=["Vnom"], inplace=True)
167
+ df = df.astype({"CursDate": "period[D]"}, copy=False)
168
+ df = df.astype({"Vcurs": "float"}, copy=False)
169
+ df.set_index("CursDate", inplace=True, verify_integrity=True)
170
+ df.sort_index(ascending=True, inplace=True)
171
+ s = df.squeeze(axis=1) # all outputs must be pd.Series
172
+ s = pad_missing_periods(s, freq="D")
173
+ s.index.rename("date", inplace=True)
174
+ if period.upper() == "M":
175
+ s = s.resample("M").last()
176
+ s = calculate_inverse_rate(s) if method == "inverse" else s
177
+ return s.rename(symbol)
@@ -0,0 +1,147 @@
1
+ from typing import Union
2
+ from datetime import datetime, date
3
+ import pandas as pd
4
+
5
+
6
+ def pad_missing_periods(
7
+ ts: Union[pd.Series, pd.DataFrame], freq: str = "D"
8
+ ) -> Union[pd.Series, pd.DataFrame]:
9
+ """
10
+ Pad missing dates and values in the time series.
11
+ """
12
+ name = ts.index.name
13
+ if not isinstance(ts.index, pd.PeriodIndex):
14
+ ts.index = ts.index.to_period(freq)
15
+ ts.sort_index(
16
+ ascending=True, inplace=True
17
+ ) # The order should be ascending to make new Period index
18
+ idx = pd.period_range(start=ts.index[0], end=ts.index[-1], freq=freq)
19
+ ts = ts.reindex(idx, method="pad")
20
+ ts.index.rename(name, inplace=True)
21
+ return ts
22
+
23
+
24
+ def calculate_inverse_rate(close_ts):
25
+ """
26
+ Inverse close values for currency rate data.
27
+ """
28
+ return 1.0 / close_ts
29
+
30
+
31
+ def set_datetime_index(data):
32
+ """
33
+ Set datetime index for DataFrame by detecting date columns.
34
+ """
35
+ if not isinstance(data.index, pd.DatetimeIndex):
36
+ for col in data.columns:
37
+ if any(keyword in str(col) for keyword in ["CDate", "DateMet", "D0", "DT"]):
38
+ data[col].str.split("T").str[0]
39
+ data.index = pd.DatetimeIndex(
40
+ pd.to_datetime(data[col], utc=True)
41
+ ).tz_convert(None)
42
+ data.index.name = "DATE"
43
+ data.drop(col, axis=1, inplace=True)
44
+ break
45
+ return data
46
+
47
+
48
+ def remove_unnecessary_columns(data):
49
+ """
50
+ Remove unnecessary columns from DataFrame.
51
+ """
52
+ data.drop(
53
+ columns=[
54
+ col
55
+ for col in ["id", "rowOrder", "vol", "DateUpdate"]
56
+ if col in data.columns
57
+ ],
58
+ inplace=True,
59
+ )
60
+ return data
61
+
62
+
63
+ def unstack_groups(data, symbol):
64
+ """
65
+ Unstack grouped data based on symbol type.
66
+ """
67
+ if symbol == "DrgMet":
68
+ data = data.groupby([data.index, "CodMet"])["price"].first().unstack()
69
+ data.columns.name = None
70
+
71
+ if symbol == "MKR":
72
+ data = (
73
+ data.groupby([data.index, "p1"])[["d1", "d7", "d30", "d90", "d180", "d360"]]
74
+ .first()
75
+ .unstack(level="p1")
76
+ )
77
+ data.columns = data.columns.rename(None, level=1)
78
+ data.columns.name = None
79
+
80
+ return data
81
+
82
+
83
+ def column_rename(data, level_0, level_1):
84
+ """
85
+ Rename columns based on mapping dictionaries.
86
+ """
87
+ if isinstance(data.columns, pd.MultiIndex):
88
+ if level_0:
89
+ new_level_0 = data.columns.levels[0].map(lambda x: level_0.get(str(x), x))
90
+ data.columns = data.columns.set_levels(new_level_0, level=0)
91
+
92
+ if level_1:
93
+ new_level_1 = data.columns.levels[1].map(lambda x: level_1.get(str(x), x))
94
+ data.columns = data.columns.set_levels(new_level_1, level=1)
95
+
96
+ else:
97
+ if level_1 and isinstance(level_1, dict):
98
+ data = data.rename(columns=level_1)
99
+ available_columns = [col for col in level_1.values() if col in data.columns]
100
+ data = data[available_columns] if available_columns else data
101
+
102
+ else:
103
+ if level_1 and not isinstance(level_1, dict):
104
+ if len(data.columns) == 1:
105
+ data = data.rename(columns={data.columns[0]: str(level_1)})
106
+ return data
107
+
108
+
109
+ def normalize_data(data, period, level_0=None, level_1=None, symbol=None):
110
+ """
111
+ Normalize time series data through multiple processing steps.
112
+ """
113
+ if isinstance(data, pd.Series):
114
+ data = data.to_frame()
115
+
116
+ set_datetime_index(data)
117
+
118
+ remove_unnecessary_columns(data)
119
+
120
+ data = unstack_groups(data, symbol)
121
+
122
+ data = column_rename(data, level_0, level_1)
123
+
124
+ data = pad_missing_periods(data)
125
+
126
+ if period.upper() == "M":
127
+ data = data.resample("M").last()
128
+
129
+ if len(data.columns) == 1:
130
+ data = data.squeeze()
131
+
132
+ return data
133
+
134
+
135
+ def guess_date(input_date, default_value):
136
+ """
137
+ Create data in datetime format.
138
+ CBR accepts "%Y-%m-%d" format only.
139
+ """
140
+ if input_date:
141
+ try:
142
+ date = datetime.strptime(input_date, "%Y-%m-%d")
143
+ except ValueError:
144
+ date = datetime.strptime(input_date, "%Y-%m")
145
+ else:
146
+ date = datetime.strptime(default_value, "%Y-%m-%d")
147
+ return date
@@ -0,0 +1,71 @@
1
+ from datetime import datetime, date
2
+ from typing import Optional
3
+
4
+ import pandas as pd
5
+
6
+ from cbrapi.cbr_settings import make_cbr_client
7
+ from cbrapi.helpers import normalize_data, guess_date
8
+
9
+
10
+ today = date.today()
11
+
12
+
13
+ def get_metals_prices(
14
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "D"
15
+ ) -> pd.DataFrame:
16
+ """
17
+ Get precious metals prices time series from CBR.
18
+
19
+ Parameters
20
+ ----------
21
+ first_date : str, optional
22
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
23
+ '1999-10-01'.
24
+
25
+ last_date : str, optional
26
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
27
+ current date.
28
+
29
+ period : {'D'}, default 'D'
30
+ Data periodicity. Currently only daily ('D') frequency is supported.
31
+
32
+ Returns
33
+ -------
34
+ pd.DataFrame
35
+ DataFrame with datetime index and the following columns:
36
+ - GOLD : Gold price (RUB per gram)
37
+ - SILVER : Silver price (RUB per gram)
38
+ - PLATINUM : Platinum price (RUB per gram)
39
+ - PALLADIUM : Palladium price (RUB per gram)
40
+
41
+ Notes
42
+ -----
43
+ Prices are provided in Russian Rubles per gram.
44
+ Data is available from October 1999.
45
+
46
+ Examples
47
+ --------
48
+ >>> get_metals_prices('2023-01-01', '2023-12-31')
49
+ >>> get_metals_prices(period='M')
50
+ """
51
+ cbr_client = make_cbr_client()
52
+ data1 = guess_date(first_date, default_value="1999-10-01")
53
+ data2 = guess_date(last_date, default_value=str(today))
54
+ metals_xml = cbr_client.service.DragMetDynamic(data1, data2)
55
+
56
+ try:
57
+ df = pd.read_xml(metals_xml, xpath=".//DrgMet")
58
+ except ValueError:
59
+ return pd.Series()
60
+
61
+ level_1_column_mapping = {
62
+ 1: "GOLD",
63
+ 2: "SILVER",
64
+ 3: "PLATINUM",
65
+ 4: "PALLADIUM",
66
+ }
67
+
68
+ df = normalize_data(
69
+ data=df, period=period, symbol="DrgMet", level_1=level_1_column_mapping
70
+ )
71
+ return df
@@ -0,0 +1,171 @@
1
+ from datetime import datetime, date
2
+ from typing import Optional
3
+
4
+ import pandas as pd
5
+
6
+ from cbrapi.cbr_settings import make_cbr_client
7
+ from cbrapi.helpers import normalize_data, guess_date
8
+
9
+
10
+ today = date.today()
11
+
12
+
13
+ def get_key_rate(
14
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "D"
15
+ ) -> pd.Series:
16
+ """
17
+ Get the key rate time series from CBR.
18
+
19
+ Parameters
20
+ ----------
21
+ first_date : str, optional
22
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
23
+ '2013-09-13'.
24
+
25
+ last_date : str, optional
26
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
27
+ current date.
28
+
29
+ period : {'D'}, default 'D'
30
+ Data periodicity. Currently only daily ('D') frequency is supported.
31
+
32
+ Returns
33
+ -------
34
+ pd.Series
35
+ Time series of key rate values with datetime index.
36
+ Rates are returned as decimals (e.g., 0.075 for 7.5%).
37
+
38
+ Notes
39
+ -----
40
+ The key rate is the main instrument of the Bank of Russia's monetary policy.
41
+ It influences interest rates in the economy and is used for liquidity provision
42
+ and absorption operations.
43
+
44
+ Examples
45
+ --------
46
+ >>> get_key_rate('2023-01-01', '2023-12-31')
47
+ >>> get_key_rate(period='D')
48
+ """
49
+ cbr_client = make_cbr_client()
50
+ data1 = guess_date(first_date, default_value="2013-09-13")
51
+ data2 = guess_date(last_date, default_value=str(today))
52
+ key_rate_xml = cbr_client.service.KeyRate(data1, data2)
53
+
54
+ try:
55
+ df = pd.read_xml(key_rate_xml, xpath=".//KR")
56
+ except ValueError:
57
+ return pd.Series()
58
+
59
+ level_1_column_mapping = {"Rate": "KEY_RATE"}
60
+
61
+ df = normalize_data(
62
+ data=df, period=period, symbol="KEY_RATE", level_1=level_1_column_mapping
63
+ )
64
+ return df
65
+
66
+
67
+ def get_ibor(
68
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "M"
69
+ ) -> pd.DataFrame:
70
+ """
71
+ Get Interbank Offered Rate and related interbank rates from CBR.
72
+
73
+ Parameters
74
+ ----------
75
+ first_date : str, optional
76
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
77
+ '2013-09-13'.
78
+
79
+ last_date : str, optional
80
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
81
+ current date.
82
+
83
+ period : {'M'}, default 'M'
84
+ Data periodicity. Currently only monthly ('M') frequency is supported.
85
+
86
+ Returns
87
+ -------
88
+ pd.DataFrame
89
+ Multi-level DataFrame with datetime index containing interbank rates.
90
+ First level columns represent tenors, second level represents rate types:
91
+
92
+ Available loan terms:
93
+ - D1 : 1 day
94
+ - D7 : 7 days
95
+ - D30 : 30 days
96
+ - D180 : 180 days
97
+ - D360 : 360 days
98
+
99
+ Rate types include:
100
+ - MIBID_RUB : Moscow Interbank Bid Rate (RUB)
101
+ - MIBOR_RUB : Moscow Interbank Offered Rate (RUB)
102
+ - MIACR_RUB : Moscow Interbank Actual Credit Rate (RUB)
103
+ - MIACR_IG_RUB : MIACR for investment grade (RUB)
104
+ - MIACR_RUB_TURNOVER : MIACR turnover (RUB)
105
+ - MIACR_IG_RUB_TURNOVER : MIACR IG turnover (RUB)
106
+ - MIACR_B_RUB : MIACR for banks (RUB)
107
+ - MIACR_B_RUB_TURNOVER : MIACR banks turnover (RUB)
108
+ - MIBID_USD : Moscow Interbank Bid Rate (USD)
109
+ - MIBOR_USD : Moscow Interbank Offered Rate (USD)
110
+ - MIACR_USD : Moscow Interbank Actual Credit Rate (USD)
111
+ - MIACR_IG_USD : MIACR for investment grade (USD)
112
+ - MIACR_USD_TURNOVER : MIACR turnover (USD)
113
+ - MIACR_IG_USD_TURNOVER : MIACR IG turnover (USD)
114
+ - MIACR_B_USD : MIACR for banks (USD)
115
+ - MIACR_B_USD_TURNOVER : MIACR banks turnover (USD)
116
+
117
+ Notes
118
+ -----
119
+ All rates are returned as decimals (e.g., 0.05 for 5%).
120
+ Turnover values represent trading volumes.
121
+
122
+ Examples
123
+ --------
124
+ >>> get_ibor('2023-01-01', '2023-12-31')
125
+ >>> get_ibor(period='M')
126
+ """
127
+ cbr_client = make_cbr_client()
128
+ data1 = guess_date(first_date, default_value="2013-09-13")
129
+ data2 = guess_date(last_date, default_value=str(today))
130
+ mkr_xml = cbr_client.service.MKR(data1, data2)
131
+
132
+ try:
133
+ df = pd.read_xml(mkr_xml, xpath=".//MKR")
134
+ except ValueError:
135
+ return pd.Series()
136
+
137
+ level_0_column_mapping = {
138
+ "d1": "D1",
139
+ "d7": "D7",
140
+ "d30": "D30",
141
+ "d180": "D180",
142
+ "d360": "D360",
143
+ }
144
+
145
+ level_1_column_mapping = {
146
+ "1": "MIBID_RUB",
147
+ "2": "MIBOR_RUB",
148
+ "3": "MIACR_RUB",
149
+ "4": "MIACR_IG_RUB",
150
+ "5": "MIACR_RUB_TURNOVER",
151
+ "6": "MIACR_IG_RUB_TURNOVER",
152
+ "7": "MIACR_B_RUB",
153
+ "8": "MIACR_B_RUB_TURNOVER",
154
+ "9": "MIBID_USD",
155
+ "10": "MIBOR_USD",
156
+ "11": "MIACR_USD",
157
+ "12": "MIACR_IG_USD",
158
+ "13": "MIACR_USD_TURNOVER",
159
+ "14": "MIACR_IG_USD_TURNOVER",
160
+ "15": "MIACR_B_USD",
161
+ "16": "MIACR_B_USD_TURNOVER",
162
+ }
163
+
164
+ df = normalize_data(
165
+ data=df,
166
+ period=period,
167
+ symbol="MKR",
168
+ level_0=level_0_column_mapping,
169
+ level_1=level_1_column_mapping,
170
+ )
171
+ return df
@@ -0,0 +1,81 @@
1
+ from datetime import datetime, date
2
+ from typing import Optional
3
+
4
+ import pandas as pd
5
+
6
+ from cbrapi.cbr_settings import make_cbr_client
7
+ from cbrapi.helpers import normalize_data, guess_date
8
+
9
+
10
+ today = date.today()
11
+
12
+
13
+ def get_mrrf(
14
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "M"
15
+ ) -> pd.DataFrame:
16
+ """
17
+ Get International Reserves and Foreign Currency Liquidity data from CBR.
18
+
19
+ Parameters
20
+ ----------
21
+ first_date : str, optional
22
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
23
+ '1999-01-01'.
24
+
25
+ last_date : str, optional
26
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
27
+ current date.
28
+
29
+ period : {'M'}, default 'M'
30
+ Data periodicity. Currently only monthly ('M') frequency is supported.
31
+
32
+ Returns
33
+ -------
34
+ pd.DataFrame
35
+ DataFrame with datetime index and the following columns:
36
+ - TOTAL_RESERVES : Total international reserves (USD)
37
+ - CURRENCY_RESERVES : Currency reserves (USD)
38
+ - FOREIGN_CURRENCY : Foreign currency holdings (USD)
39
+ - SDR_ACCOUNT : Special Drawing Rights (SDR) account (USD)
40
+ - IMF_RESERVE : Reserve position in IMF (USD)
41
+ - MONETARY_GOLD : Monetary gold holdings (USD)
42
+
43
+ Notes
44
+ -----
45
+ International reserves are external assets that are readily available to and
46
+ controlled by monetary authorities for:
47
+ - Meeting balance of payments financing needs
48
+ - Intervention in exchange markets to affect currency exchange rate
49
+ - Other related purposes
50
+
51
+ All values are reported in US dollars.
52
+
53
+ Examples
54
+ --------
55
+ >>> get_mrrf('2020-01-01', '2023-12-31')
56
+ >>> get_mrrf(period='M')
57
+ """
58
+ cbr_client = make_cbr_client()
59
+ data1 = guess_date(first_date, default_value="1999-01-01")
60
+ data2 = guess_date(last_date, default_value=str(today))
61
+ mrrf_xml = cbr_client.service.mrrf(data1, data2)
62
+
63
+ try:
64
+ df = pd.read_xml(mrrf_xml, xpath=".//mr")
65
+ except ValueError:
66
+ return pd.Series()
67
+
68
+ level_1_column_mapping = {
69
+ "p1": "TOTAL_RESERVES",
70
+ "p2": "CURRENCY_RESERVES",
71
+ "p3": "FOREIGN_CURRENCY",
72
+ "p4": "SDR_ACCOUNT",
73
+ "p5": "IMF_RESERVE",
74
+ "p6": "MONETARY_GOLD",
75
+ }
76
+
77
+ df = normalize_data(
78
+ data=df, period=period, symbol="mr", level_1=level_1_column_mapping
79
+ )
80
+
81
+ return df
@@ -0,0 +1,257 @@
1
+ from datetime import datetime, date
2
+ from typing import Optional
3
+
4
+ import pandas as pd
5
+
6
+ from cbrapi.cbr_settings import make_cbr_client
7
+ from cbrapi.helpers import normalize_data, guess_date
8
+
9
+
10
+ today = date.today()
11
+
12
+
13
+ def get_ruonia_ts(
14
+ symbol: str,
15
+ first_date: Optional[str] = None,
16
+ last_date: Optional[str] = None,
17
+ period: str = "D",
18
+ ) -> pd.Series:
19
+ """
20
+ Get RUONIA (Ruble Overnight Index Average) time series data from CBR.
21
+
22
+ Parameters
23
+ ----------
24
+ symbol : str
25
+ Financial instrument symbol. Supported symbols:
26
+ - 'RUONIA.INDX' : RUONIA index
27
+ - 'RUONIA_AVG_1M.RATE' : 1-month average rate
28
+ - 'RUONIA_AVG_3M.RATE' : 3-month average rate
29
+ - 'RUONIA_AVG_6M.RATE' : 6-month average rate
30
+ - Other symbols : return overnight RUONIA rates
31
+
32
+ first_date : str, optional
33
+ Start date in format 'YYYY-MM-DD'. If not specified, returns
34
+ data from the earliest available date.
35
+
36
+ last_date : str, optional
37
+ End date in format 'YYYY-MM-DD'. If not specified, returns
38
+ data up to the most recent available date.
39
+
40
+ period : {'D'}, default 'D'
41
+ Data periodicity. Currently only daily ('D') frequency is supported.
42
+
43
+ Returns
44
+ -------
45
+ pd.Series
46
+ Time series data for the requested symbol with datetime index.
47
+ Returns empty Series if no data is available for the given parameters.
48
+
49
+ Notes
50
+ -----
51
+ Data is sourced from the Central Bank of Russia (CBR) official statistics.
52
+ The function handles API requests and data parsing from CBR web services.
53
+
54
+ Examples
55
+ --------
56
+ >>> get_ruonia_ts('RUONIA.INDX', '2023-01-01', '2023-12-31')
57
+ >>> get_ruonia_ts('RUONIA_AVG_3M.RATE')
58
+ """
59
+ cbr_client = make_cbr_client()
60
+ if symbol in [
61
+ "RUONIA.INDX",
62
+ "RUONIA_AVG_1M.RATE",
63
+ "RUONIA_AVG_3M.RATE",
64
+ "RUONIA_AVG_6M.RATE",
65
+ ]:
66
+ ticker = (
67
+ symbol.split(".")[0] if symbol.split(".")[1] == "RATE" else "RUONIA_INDEX"
68
+ )
69
+ df = get_ruonia_index(first_date, last_date).loc[:, ticker]
70
+ if symbol != "RUONIA.INDX":
71
+ df /= 100
72
+ return normalize_data(df, period, symbol)
73
+ else:
74
+ return get_ruonia_overnight(first_date, last_date, period)
75
+
76
+
77
+ def get_ruonia_index(
78
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "D"
79
+ ) -> pd.DataFrame:
80
+ """
81
+ Get RUONIA index and averages time series from CBR.
82
+
83
+ Parameters
84
+ ----------
85
+ first_date : str, optional
86
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
87
+ '2010-01-01'.
88
+
89
+ last_date : str, optional
90
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
91
+ current date.
92
+
93
+ period : {'D'}, default 'D'
94
+ Data periodicity. Currently only daily ('D') frequency is supported.
95
+
96
+ Returns
97
+ -------
98
+ pd.DataFrame
99
+ DataFrame with datetime index and the following columns:
100
+ - RUONIA_INDEX : RUONIA index value
101
+ - RUONIA_AVG_1M : 1-month average rate (as decimal)
102
+ - RUONIA_AVG_3M : 3-month average rate (as decimal)
103
+ - RUONIA_AVG_6M : 6-month average rate (as decimal)
104
+
105
+ Notes
106
+ -----
107
+ RUONIA (Ruble Overnight Index Average) is the weighted average interest rate
108
+ on interbank loans and deposits. It serves as an indicator of the cost of
109
+ unsecured overnight borrowing.
110
+
111
+ Examples
112
+ --------
113
+ >>> get_ruonia_index('2023-01-01', '2023-12-31')
114
+ >>> get_ruonia_index(period='D')
115
+ """
116
+ cbr_client = make_cbr_client()
117
+ data1 = guess_date(first_date, default_value="2010-01-01")
118
+ data2 = guess_date(last_date, default_value=str(today))
119
+ ruonia_index_xml = cbr_client.service.RuoniaSV(data1, data2)
120
+
121
+ try:
122
+ df = pd.read_xml(ruonia_index_xml, xpath=".//ra")
123
+ except ValueError:
124
+ return pd.Series()
125
+
126
+ level_1_column_mapping = {
127
+ "RUONIA_Index": "RUONIA_INDEX",
128
+ "R1W": "RUONIA_AVG_1M",
129
+ "R2W": "RUONIA_AVG_3M",
130
+ "R1M": "RUONIA_AVG_6M",
131
+ }
132
+
133
+ df = normalize_data(
134
+ data=df, period=period, symbol="ra", level_1=level_1_column_mapping
135
+ )
136
+ return df
137
+
138
+
139
+ def get_ruonia_overnight(
140
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "D"
141
+ ) -> pd.Series:
142
+ """
143
+ Get RUONIA overnight value time series from CBR.
144
+
145
+ Parameters
146
+ ----------
147
+ first_date : str, optional
148
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
149
+ '2010-01-01'.
150
+
151
+ last_date : str, optional
152
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
153
+ current date.
154
+
155
+ period : {'D'}, default 'D'
156
+ Data periodicity. Currently only daily ('D') frequency is supported.
157
+
158
+ Returns
159
+ -------
160
+ pd.Series
161
+ Time series of RUONIA overnight rates with datetime index.
162
+ Rates are returned as decimals (e.g., 0.05 for 5%).
163
+
164
+ Notes
165
+ -----
166
+ RUONIA (Ruble Overnight Index Average) is the weighted average interest rate
167
+ on interbank loans and deposits. It serves as an indicator of the cost of
168
+ unsecured overnight borrowing.
169
+
170
+ Examples
171
+ --------
172
+ >>> get_ruonia_overnight('2023-01-01', '2023-12-31')
173
+ >>> get_ruonia_overnight(period='D')
174
+ """
175
+ cbr_client = make_cbr_client()
176
+ data1 = guess_date(first_date, default_value="2010-01-01")
177
+ data2 = guess_date(last_date, default_value=str(date.today()))
178
+ ruonia_overnight_xml = cbr_client.service.Ruonia(data1, data2)
179
+
180
+ try:
181
+ df = pd.read_xml(ruonia_overnight_xml, xpath="//ro")
182
+ except ValueError:
183
+ return pd.Series()
184
+
185
+ level_1_column_mapping = {
186
+ "ruo": "RUONIA_OVERNIGHT",
187
+ }
188
+
189
+ df = normalize_data(
190
+ data=df, period=period, symbol="ro", level_1=level_1_column_mapping
191
+ )
192
+ df /= 100
193
+ return df
194
+
195
+
196
+ def get_roisfix(
197
+ first_date: Optional[str] = None, last_date: Optional[str] = None, period: str = "D"
198
+ ) -> pd.DataFrame:
199
+ """
200
+ Get ROISfix (Ruble Overnight Index Swap Fixing) time series from CBR.
201
+
202
+ Parameters
203
+ ----------
204
+ first_date : str, optional
205
+ Start date in format 'YYYY-MM-DD'. If not specified, defaults to
206
+ '2011-04-15'.
207
+
208
+ last_date : str, optional
209
+ End date in format 'YYYY-MM-DD'. If not specified, defaults to
210
+ current date.
211
+
212
+ period : {'D'}, default 'D'
213
+ Data periodicity. Currently only daily ('D') frequency is supported.
214
+
215
+ Returns
216
+ -------
217
+ pd.DataFrame
218
+ DataFrame with datetime index and the following columns:
219
+ - RATE_1_WEEK : 1-week ROISfix rate (as decimal)
220
+ - RATE_2_WEEK : 2-week ROISfix rate (as decimal)
221
+ - RATE_1_MONTH : 1-month ROISfix rate (as decimal)
222
+ - RATE_2_MONTH : 2-month ROISfix rate (as decimal)
223
+ - RATE_3_MONTH : 3-month ROISfix rate (as decimal)
224
+ - RATE_6_MONTH : 6-month ROISfix rate (as decimal)
225
+
226
+ Notes
227
+ -----
228
+ ROISfix represents the fixed rate in ruble overnight index swaps.
229
+
230
+ Examples
231
+ --------
232
+ >>> get_roisfix('2023-01-01', '2023-12-31')
233
+ >>> get_roisfix(period='D')
234
+ """
235
+ cbr_client = make_cbr_client()
236
+ data1 = guess_date(first_date, default_value="2011-04-15")
237
+ data2 = guess_date(last_date, default_value=str(today))
238
+ roisfix_xml = cbr_client.service.ROISfix(data1, data2)
239
+
240
+ try:
241
+ df = pd.read_xml(roisfix_xml, xpath=".//rf")
242
+ except ValueError:
243
+ return pd.Series()
244
+
245
+ level_1_column_mapping = {
246
+ "R1W": "RATE_1_WEEK",
247
+ "R2W": "RATE_2_WEEK",
248
+ "R1M": "RATE_1_MONTH",
249
+ "R2M": "RATE_2_MONTH",
250
+ "R3M": "RATE_3_MONTH",
251
+ "R6M": "RATE_6_MONTH",
252
+ }
253
+
254
+ df = normalize_data(
255
+ data=df, period=period, symbol="rf", level_1=level_1_column_mapping
256
+ )
257
+ return df
@@ -0,0 +1,25 @@
1
+ [tool.poetry]
2
+ name = "cbrapi"
3
+ version = "0.1.0"
4
+ description = "Python interface for Central Bank of Russia (CBR) API"
5
+ authors = [
6
+ "AAARRRT <artiomsalazov@gmail.com>",
7
+ "MBK Development LLC <info@rostsber.ru>"
8
+ ]
9
+ readme = "README.md"
10
+
11
+ [tool.poetry.dependencies]
12
+ python = ">=3.10,<4.0.0"
13
+ pandas = "^2.3.2"
14
+ requests = "*"
15
+ suds-py3 = "*"
16
+ lxml = "*"
17
+
18
+ [tool.poetry.group.dev.dependencies]
19
+ black = "^25.1.0"
20
+
21
+ [build-system]
22
+ requires = ["poetry-core"]
23
+ build-backend = "poetry.core.masonry.api"
24
+
25
+