def fetch_timeseries(providers: Dict[Callable[[Any], pd.DataFrame], List[str]], start_date: str = None, force_lower_case: bool = False, multi_index: bool = None, ffill: bool = False, **kwargs): symbol_type = (List, Tuple, Set) expected_frames = sum( len(s) if isinstance(s, symbol_type) else 1 for s in providers.values()) df = None if multi_index is None and expected_frames > 1: multi_index = True for provider, symbols in providers.items(): # make sure provider is an actual provider -> a callable if not callable(provider): provider = PROVIDER_MAP[provider] # make sure the symbols are iterable -> wrap single symbols into a list if not isinstance(symbols, symbol_type): symbols = [symbols] # fetch all symbols of all providers (later we could do this in parallel) for symbol in symbols: _df = call_callable_dynamic_args(provider, symbol, multi_index=multi_index, **kwargs) if _df is None: continue if multi_index: if not isinstance(_df.columns, pd.MultiIndex): _df = add_multi_index(_df, symbol, True) if force_lower_case: _df.columns = pd.MultiIndex.from_tuples([ (h.lower(), c.lower()) for h, c in _df.columns.to_list() ]) else: if isinstance(_df.columns, pd.MultiIndex): _df.columns = [t[-1] for t in _df.columns.to_list()] if force_lower_case: _df.columns = [c.lower() for c in _df.columns.to_list()] if df is None: df = _df else: df = inner_join(df, _df, force_multi_index=multi_index, ffill=ffill) return df if start_date is None else df[start_date:]
def fetch_yahoo(*args: str, period: str = 'max', multi_index: bool = False, **kwargs: str): df = None if len(args) == 1: df = __download_yahoo_data(args[0], period) else: # convert args to kwargs if len(args) > 0: kwargs = merge_kwargs({arg: arg for arg in args}, kwargs) for k, v in kwargs.items(): px = f'{k}_' df_ = __download_yahoo_data(v, period) if multi_index: df_.columns = pd.MultiIndex.from_product([[k], df_.columns]) if df is None: df = df_ else: df = inner_join(df, df_) else: if df is None: df = df_.add_prefix(px) else: df = inner_join(df, df_, prefix=px) # print some statistics if df is None: logging.warning("nothing downloaded") else: logging.info( f'number of rows for joined dataframe = {len(df)}, from {df.index[0]} to {df.index[-1]}' ) return df
def ta_multi_ma(df: _t.PatchedDataFrame, average_function='sma', period=12, factors=_np.linspace(1 - 0.2, 1 + 0.2, 5)) -> _t.PatchedDataFrame: ma = {'sma': ta_sma, 'ema': ta_ema, 'wilder': ta_wilders} res = _pd.DataFrame({}, index=df.index) if df.ndim > 1: res = None for col in df.columns.to_list(): _df = ta_multi_ma(df[col], average_function, period, factors) _df = add_multi_index(_df, col) res = inner_join(res, _df, force_multi_index=True) return res for x in factors: res[f"{df.name}_{average_function}({period})({x:.3f})"] = ma[average_function](df, period) * x return res