def get_history_window(self, assets, end_dt, bar_count, frequency, field, data_frequency=None, is_current=False): """ Public API method that returns a dataframe containing the requested history window. Data is fully adjusted. Parameters ---------- assets : list[TradingPair] The assets whose data is desired. end_dt: datetime The date of the last bar bar_count: int The number of bars desired. frequency: string "1d" or "1m" field: string The desired field of the asset. data_frequency: string The frequency of the data to query; i.e. whether the data is 'daily' or 'minute' bars. is_current: bool Skip date filters when current data is requested (last few bars until now). Notes ----- Catalysts requires an end data with bar count both CCXT wants a start data with bar count. Since we have to make calculations here, we ensure that the last candle match the end_dt parameter. Returns ------- DataFrame A dataframe containing the requested data. """ freq, candle_size, unit, data_frequency = get_frequency( frequency, data_frequency, supported_freqs=['T', 'D', 'H']) # we want to avoid receiving empty candles # so we request more than needed # TODO: consider defining a const per asset # and/or some retry mechanism (in each iteration request more data) min_candles_number = get_candles_number_from_minutes( unit, candle_size, self.MIN_MINUTES_REQUESTED) requested_bar_count = bar_count if requested_bar_count < min_candles_number: requested_bar_count = min_candles_number # The get_history method supports multiple asset candles = self.get_candles( freq=freq, assets=assets, bar_count=requested_bar_count, end_dt=end_dt if not is_current else None, ) # candles sanity check - verify no empty candles were received: for asset in candles: if not candles[asset]: raise NoCandlesReceivedFromExchange( bar_count=requested_bar_count, end_dt=end_dt, asset=asset, exchange=self.name) # for avoiding unnecessary forward fill end_dt is taken back one second forward_fill_till_dt = end_dt - timedelta(seconds=1) series = get_candles_df(candles=candles, field=field, freq=frequency, bar_count=requested_bar_count, end_dt=forward_fill_till_dt) # TODO: consider how to approach this edge case # delta_candle_size = candle_size * 60 if unit == 'H' else candle_size # Checking to make sure that the dates match # delta = get_delta(delta_candle_size, data_frequency) # adj_end_dt = end_dt - delta # last_traded = asset_series.index[-1] # if last_traded < adj_end_dt: # raise LastCandleTooEarlyError( # last_traded=last_traded, # end_dt=adj_end_dt, # exchange=self.name, # ) df = pd.DataFrame(series) df.dropna(inplace=True) return df.tail(bar_count)
def get_history_window_for_asset(self, asset, end_dt, bar_count, frequency, fields, data_frequency=None, is_current=False): """ Public API method that returns a dataframe containing the requested history window. Data is fully adjusted. Parameters ---------- asset : TradingPair The asset whose data is desired. end_dt: datetime The date of the last bar bar_count: int The number of bars desired. frequency: string "1d" or "1m" fields: string The desired fields of the asset. data_frequency: string The frequency of the data to query; i.e. whether the data is 'daily' or 'minute' bars. is_current: bool Skip date filters when current data is requested (last few bars until now). Notes ----- Catalysts requires an end data with bar count both CCXT wants a start data with bar count. Since we have to make calculations here, we ensure that the last candle match the end_dt parameter. Returns ------- DataFrame A dataframe containing the requested data. """ freq, candle_size, unit, data_frequency = get_frequency( frequency, data_frequency, supported_freqs=['T', 'D', 'H']) # we want to avoid receiving empty candles # so we request more than needed # TODO: consider defining a const per asset # and/or some retry mechanism (in each iteration request more data) min_candles_number = get_candles_number_from_minutes( unit, candle_size, self.MIN_MINUTES_REQUESTED) requested_bar_count = bar_count if requested_bar_count < min_candles_number: requested_bar_count = min_candles_number candles = self.get_candles( freq=freq, assets= asset, # when we pass a single asset, the response is a flat DataFrame with the fields as columns bar_count=requested_bar_count, end_dt=end_dt if not is_current else None, ) # candles sanity check - verify no empty candles were received: if len(candles) == 0: raise NoCandlesReceivedFromExchange(bar_count=requested_bar_count, end_dt=end_dt, asset=asset, exchange=self.name) # for avoiding unnecessary forward fill end_dt is taken back one second forward_fill_till_dt = end_dt - timedelta(seconds=1) candles_df = get_candles_df_for_asset(candles=candles, fields=fields, freq=frequency, bar_count=requested_bar_count, end_dt=forward_fill_till_dt) return candles_df.tail(bar_count)