Skip to content

Commit 2d8a882

Browse files
committed
feat: add parallel data requests to ListMaker
1 parent 43284f7 commit 2d8a882

File tree

2 files changed

+216
-26
lines changed

2 files changed

+216
-26
lines changed

main_notebook.ipynb

Lines changed: 195 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
"is_executing": true
88
},
99
"ExecuteTime": {
10-
"end_time": "2025-02-07T08:15:18.344499Z",
11-
"start_time": "2025-02-07T08:15:18.106102Z"
10+
"end_time": "2025-03-03T13:29:17.198078Z",
11+
"start_time": "2025-03-03T13:29:16.958633Z"
1212
}
1313
},
1414
"source": [
@@ -44,7 +44,7 @@
4444
]
4545
}
4646
],
47-
"execution_count": 63
47+
"execution_count": 10
4848
},
4949
{
5050
"cell_type": "code",
@@ -54,8 +54,8 @@
5454
"outputs_hidden": false
5555
},
5656
"ExecuteTime": {
57-
"end_time": "2025-02-07T07:52:40.917254Z",
58-
"start_time": "2025-02-07T07:52:40.871639Z"
57+
"end_time": "2025-03-03T13:29:19.540348Z",
58+
"start_time": "2025-03-03T13:29:19.496959Z"
5959
}
6060
},
6161
"source": [
@@ -68,28 +68,194 @@
6868
"'1.4.4'"
6969
]
7070
},
71-
"execution_count": 2,
71+
"execution_count": 11,
7272
"metadata": {},
7373
"output_type": "execute_result"
7474
}
7575
],
76-
"execution_count": 2
76+
"execution_count": 11
77+
},
78+
{
79+
"metadata": {},
80+
"cell_type": "markdown",
81+
"source": "## List Maker (Parallel)"
7782
},
7883
{
7984
"metadata": {
8085
"ExecuteTime": {
81-
"end_time": "2025-02-07T08:15:24.896180Z",
82-
"start_time": "2025-02-07T08:15:24.846667Z"
86+
"end_time": "2025-03-03T14:13:37.392135Z",
87+
"start_time": "2025-03-03T14:13:37.345010Z"
8388
}
8489
},
8590
"cell_type": "code",
8691
"source": [
87-
"assets = ['MCFTR.INDX', 'GC.COMM', 'RGBITR.INDX', 'RUCBTRNS.INDX']\n",
88-
"assets1 = ['MCFTR.INDX', 'GC.COMM']\n",
89-
"assets2 = ['SPY.US', 'AGG.US', 'GC.COMM']"
92+
"from okama.common import make_asset_list\n",
93+
"\n",
94+
"ls = ['SPY.US', 'AGG.US', 'GC.COMM', 'VOO.US', 'MCFTR.INDX', 'RGBITR.INDX', 'MOW_PR.RE', 'MOW_SEC.RE', 'RUCBTRNS.INDX', 'USDRUB.FX']\n"
9095
],
9196
"outputs": [],
92-
"execution_count": 64
97+
"execution_count": 29
98+
},
99+
{
100+
"metadata": {
101+
"ExecuteTime": {
102+
"end_time": "2025-03-03T14:13:43.861842Z",
103+
"start_time": "2025-03-03T14:13:38.987957Z"
104+
}
105+
},
106+
"cell_type": "code",
107+
"source": "make_asset_list.ListMaker._get_asset_obj_dict(ls)",
108+
"outputs": [
109+
{
110+
"data": {
111+
"text/plain": [
112+
"{'SPY.US': symbol SPY.US\n",
113+
" name SPDR S&P 500 ETF Trust\n",
114+
" country USA\n",
115+
" exchange NYSE ARCA\n",
116+
" currency USD\n",
117+
" type ETF\n",
118+
" isin US78462F1030\n",
119+
" first date 1993-02\n",
120+
" last date 2025-02\n",
121+
" period length 32.00\n",
122+
" dtype: object,\n",
123+
" 'AGG.US': symbol AGG.US\n",
124+
" name iShares Core U.S. Aggregate Bond ETF\n",
125+
" country USA\n",
126+
" exchange NYSE ARCA\n",
127+
" currency USD\n",
128+
" type ETF\n",
129+
" isin US4642872265\n",
130+
" first date 2003-10\n",
131+
" last date 2025-02\n",
132+
" period length 21.40\n",
133+
" dtype: object,\n",
134+
" 'GC.COMM': symbol GC.COMM\n",
135+
" name Gold (COMEX)\n",
136+
" country USA\n",
137+
" exchange COMM\n",
138+
" currency USD\n",
139+
" type Commodity\n",
140+
" isin \n",
141+
" first date 1975-02\n",
142+
" last date 2025-02\n",
143+
" period length 50.00\n",
144+
" dtype: object,\n",
145+
" 'VOO.US': symbol VOO.US\n",
146+
" name Vanguard S&P 500 ETF\n",
147+
" country USA\n",
148+
" exchange NYSE ARCA\n",
149+
" currency USD\n",
150+
" type ETF\n",
151+
" isin US9229083632\n",
152+
" first date 2010-10\n",
153+
" last date 2025-02\n",
154+
" period length 14.30\n",
155+
" dtype: object,\n",
156+
" 'MCFTR.INDX': symbol MCFTR.INDX\n",
157+
" name MOEX Russia Total Return Index\n",
158+
" country Russia\n",
159+
" exchange INDX\n",
160+
" currency RUB\n",
161+
" type INDEX\n",
162+
" isin \n",
163+
" first date 1997-10\n",
164+
" last date 2025-02\n",
165+
" period length 27.40\n",
166+
" dtype: object,\n",
167+
" 'RGBITR.INDX': symbol RGBITR.INDX\n",
168+
" name MOEX Government Bond Index\n",
169+
" country Russia\n",
170+
" exchange INDX\n",
171+
" currency RUB\n",
172+
" type INDEX\n",
173+
" isin \n",
174+
" first date 2003-01\n",
175+
" last date 2025-02\n",
176+
" period length 22.10\n",
177+
" dtype: object,\n",
178+
" 'MOW_PR.RE': symbol MOW_PR.RE\n",
179+
" name Moscow real estate. Primary market.\n",
180+
" country Russia\n",
181+
" exchange RE\n",
182+
" currency RUB\n",
183+
" type Real Estate\n",
184+
" isin \n",
185+
" first date 2000-04\n",
186+
" last date 2024-12\n",
187+
" period length 24.70\n",
188+
" dtype: object,\n",
189+
" 'MOW_SEC.RE': symbol MOW_SEC.RE\n",
190+
" name Moscow real estate. Secondary market.\n",
191+
" country Russia\n",
192+
" exchange RE\n",
193+
" currency RUB\n",
194+
" type Real Estate\n",
195+
" isin \n",
196+
" first date 2000-04\n",
197+
" last date 2024-12\n",
198+
" period length 24.70\n",
199+
" dtype: object,\n",
200+
" 'RUCBTRNS.INDX': symbol RUCBTRNS.INDX\n",
201+
" name Moscow Exchange Corporate Bond Index RUCBTRNS\n",
202+
" country Russia\n",
203+
" exchange INDX\n",
204+
" currency RUB\n",
205+
" type INDEX\n",
206+
" isin \n",
207+
" first date 2003-01\n",
208+
" last date 2025-02\n",
209+
" period length 22.10\n",
210+
" dtype: object,\n",
211+
" 'USDRUB.FX': symbol USDRUB.FX\n",
212+
" name Central Bank of Russia exchange rate of US Dollar\n",
213+
" country Russia\n",
214+
" exchange CBR\n",
215+
" currency RUB\n",
216+
" type Currency\n",
217+
" isin \n",
218+
" first date 1992-08\n",
219+
" last date 2025-03\n",
220+
" period length 32.60\n",
221+
" dtype: object}"
222+
]
223+
},
224+
"execution_count": 30,
225+
"metadata": {},
226+
"output_type": "execute_result"
227+
}
228+
],
229+
"execution_count": 30
230+
},
231+
{
232+
"metadata": {
233+
"ExecuteTime": {
234+
"end_time": "2025-03-03T14:14:04.024458Z",
235+
"start_time": "2025-03-03T14:13:43.933717Z"
236+
}
237+
},
238+
"cell_type": "code",
239+
"source": [
240+
"al = ok.AssetList(ls, ccy='RUB', inflation=True)\n",
241+
"print(al)"
242+
],
243+
"outputs": [
244+
{
245+
"name": "stdout",
246+
"output_type": "stream",
247+
"text": [
248+
"assets [SPY.US, AGG.US, GC.COMM, VOO.US, MCFTR.INDX, ...\n",
249+
"currency RUB\n",
250+
"first_date 2010-10\n",
251+
"last_date 2024-12\n",
252+
"period_length 14 years, 3 months\n",
253+
"inflation RUB.INFL\n",
254+
"dtype: object\n"
255+
]
256+
}
257+
],
258+
"execution_count": 31
93259
},
94260
{
95261
"cell_type": "markdown",
@@ -103,6 +269,22 @@
103269
"## DCF"
104270
]
105271
},
272+
{
273+
"metadata": {
274+
"ExecuteTime": {
275+
"end_time": "2025-03-03T13:51:34.806123Z",
276+
"start_time": "2025-03-03T13:51:34.694853Z"
277+
}
278+
},
279+
"cell_type": "code",
280+
"source": [
281+
"assets = ['MCFTR.INDX', 'GC.COMM', 'RGBITR.INDX', 'RUCBTRNS.INDX']\n",
282+
"assets1 = ['MCFTR.INDX', 'GC.COMM']\n",
283+
"assets2 = ['SPY.US', 'AGG.US', 'GC.COMM']"
284+
],
285+
"outputs": [],
286+
"execution_count": 17
287+
},
106288
{
107289
"metadata": {
108290
"ExecuteTime": {

okama/common/make_asset_list.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Dict, Optional, List, Any, Type, Union
22
from abc import ABC, abstractmethod
3+
from joblib import Parallel, delayed
34

45
import numpy as np
56
import pandas as pd
@@ -50,8 +51,8 @@ def __init__(
5051
):
5152
self._assets = list(dict.fromkeys(assets)) if assets else [settings.default_ticker]
5253
self._currency = asset.Asset(symbol=f"{ccy}.FX")
54+
self.asset_obj_dict = ListMaker._get_asset_obj_dict(self._list_of_asset_like_objects)
5355
(
54-
self.asset_obj_dict,
5556
self.first_date,
5657
self.last_date,
5758
self.newest_asset,
@@ -62,9 +63,8 @@ def __init__(
6263
self.assets_last_dates,
6364
self.assets_ror,
6465
) = self._make_list(
65-
ls=self._list_of_asset_like_objects,
6666
first_date=first_date,
67-
last_date=last_date,
67+
last_date=last_date
6868
).values()
6969
if first_date:
7070
self.first_date = max(self.first_date, pd.to_datetime(first_date))
@@ -105,15 +105,29 @@ def __len__(self):
105105
def __getitem__(self, item):
106106
return list(self.asset_obj_dict.values())[item]
107107

108-
def _make_list(self, ls: list, first_date, last_date) -> dict:
108+
@staticmethod
109+
def _get_asset_obj_dict(ls: list) -> dict:
110+
def get_item(symbol):
111+
asset_item = symbol if hasattr(symbol, "symbol") and hasattr(symbol, "ror") else asset.Asset(symbol)
112+
if asset_item.pl.years == 0 and asset_item.pl.months <= 2:
113+
raise ShortPeriodLengthError(
114+
f"{asset_item.symbol} period length is {asset_item.pl.months}. It should be at least 3 months."
115+
)
116+
return asset_item
117+
118+
asset_obj_list = Parallel(n_jobs=-1, backend="threading")(
119+
delayed(get_item)(s) for s in ls
120+
)
121+
return {obj.symbol: obj for obj in asset_obj_list}
122+
123+
def _make_list(self, first_date, last_date) -> dict:
109124
"""
110125
Make an asset list from a list of symbols.
111126
"""
112127
base_currency_ticker: str = self._currency.ticker
113128
currency_first_date: pd.Timestamp = self._currency.first_date
114129
currency_last_date: pd.Timestamp = self._currency.last_date
115130

116-
asset_obj_dict = {} # dict of Asset/Portfolio type objects
117131
own_first_dates: Dict[str, pd.Timestamp] = {}
118132
own_last_dates: Dict[str, pd.Timestamp] = {}
119133
first_dates: Dict[str, pd.Timestamp] = {}
@@ -123,15 +137,10 @@ def _make_list(self, ls: list, first_date, last_date) -> dict:
123137
df = pd.DataFrame()
124138
input_first_date = pd.to_datetime(first_date) if first_date else None
125139
input_last_date = pd.to_datetime(last_date) if last_date else None
126-
for i, x in enumerate(ls):
127-
asset_item = x if hasattr(x, "symbol") and hasattr(x, "ror") else asset.Asset(x)
140+
for i, asset_item in enumerate(self.asset_obj_dict.values()):
128141
# get asset own first and last dates
129142
asset_own_first_date = asset_item.first_date
130143
asset_own_last_date = asset_item.last_date
131-
if asset_item.pl.years == 0 and asset_item.pl.months <= 2:
132-
raise ShortPeriodLengthError(
133-
f"{asset_item.symbol} period length is {asset_item.pl.months}. It should be at least 3 months."
134-
)
135144
if i == 0: # required to use pd.concat below (df should not be empty).
136145
df = self._make_ror(asset_item, base_currency_ticker)
137146
else:
@@ -150,7 +159,6 @@ def _make_list(self, ls: list, first_date, last_date) -> dict:
150159
f"{asset_item.symbol} historical data period length is too short. " f"It must be at least 3 months."
151160
)
152161
# append data to dictionaries
153-
asset_obj_dict[asset_item.symbol] = asset_item
154162
currencies[asset_item.symbol] = asset_item.currency
155163
names[asset_item.symbol] = asset_item.name
156164
first_dates[asset_item.symbol] = asset_first_date
@@ -175,7 +183,6 @@ def _make_list(self, ls: list, first_date, last_date) -> dict:
175183
df = df.to_frame()
176184
df.columns.name = "Symbols" # required for Plotly charts
177185
return dict(
178-
asset_obj_list=asset_obj_dict,
179186
first_date=list_first_date,
180187
last_date=list_last_date,
181188
newest_asset=own_first_dates_sorted[-1][0],
@@ -187,6 +194,7 @@ def _make_list(self, ls: list, first_date, last_date) -> dict:
187194
ror=df,
188195
)
189196

197+
190198
def _make_ror(self, list_asset: asset.Asset, base_currency_name: str) -> pd.Series:
191199
"""
192200
Make asset rate of return time series.

0 commit comments

Comments
 (0)