def test_ema_20_initial_calculation(self): # INTC 2019-12-03 to 2019-12-31 price_data = [ 56.07, 56.02, 56.08, 56.81, 56.53, 56.59, 57.07, 57.55, 57.79, 57.70, 57.23, 57.17, 57.96, 58.95, 59.23, 59.41, 59.82, 60.08, 59.62, 59.85, ] # yapf: disable date = time.CivilTime(2019, 12, 31) close_prices = [ _make_close_price(value, time.FromCivil(d)) for value, d in zip(price_data, trading_days.get_last_n(date, 20)) ] # Note: this is different than the actual EMA20 for Intel on 2019/12/31, # which is 58.46, because EMA accounts for *all* past data assert_that( ema.make_ema_20d_producer().calculate(close_prices), equals_proto(f""" symbol: "TEST" data_space: STOCK_DATA data_type: EMA_20D value: 58.255796513052346 timestamp {{ seconds: {time.as_seconds(2019, 12, 31)} }}"""))
def test_raise_when_inputs_do_not_meet_accpeted_input_shapes(self): date = time.CivilTime(2017, 10, 10) close_prices = [ _make_close_price(200.0, time.FromCivil(d)) for d in trading_days.get_last_n(date, 19) ] with self.assertRaisesRegex( errors.InvalidArgumentError, 'Expecting data with input shape: data_type: CLOSE_PRICE'): ema.make_ema_20d_producer().calculate(close_prices)
def get_close_prices_for_ema20(t: time.Time, symbol: str) -> List[DataEntry]: # INTC 2019-12-03 to 2019-12-31 price_data = [ 56.07, 56.02, 56.08, 56.81, 56.53, 56.59, 57.07, 57.55, 57.79, 57.70, 57.23, 57.17, 57.96, 58.95, 59.23, 59.41, 59.82, 60.08, 59.62, 59.85, ] # yapf: disable close_prices = [ _make_close_price(symbol, value, time.FromCivil(d)) for value, d in zip(price_data, trading_days.get_last_n(time.ToCivil(t), 20)) ] random.shuffle(close_prices) return close_prices
def recursive_inputs_shape( base_calc_type: DataType.Enum, incr_calc_type: DataType.Enum, t: time.Time, time_spec: calc.CalcTimeSpecs) -> calc.RecursiveInputs: # TODO: same here, think about how to get it work with period other than # days. e.g week-based moving averages. the_day_before = trading_days.get_last_n(time.ToCivil(t), 1, include_input_date=False)[0] return (DataEntry( data_type=base_calc_type, timestamp=time_util.from_time(time.FromCivil(the_day_before)), ), DataEntry( data_type=incr_calc_type, timestamp=time_util.from_time(t), ))
def test_ema_20_for_constant_list(self): date = time.CivilTime(2017, 10, 10) close_prices = [ _make_close_price(200.0, time.FromCivil(d)) for d in trading_days.get_last_n(date, 20) ] assert_that( ema.make_ema_20d_producer().calculate(close_prices), equals_proto(f""" symbol: "TEST" data_space: STOCK_DATA data_type: EMA_20D value: 200.0 timestamp {{ seconds: {time.as_seconds(2017, 10, 10)} }}"""))
def series_source_inputs_shape( source_calc_type: DataType.Enum, t: time.Time, time_spec: calc.CalcTimeSpecs) -> calc.SourceInputs: # TODO: right now this is still no properly generalized. For time span # longer than a day, they should all work. However for day and shorter span, # they need to be checked against trading days and trading hours. # NOTE: both FromCivil and ToCivil assumes UTC, which later might # be updated to take into account the exchange timezone of a # security. timestamps = [ time.FromCivil(day) for day in trading_days.get_last_n( time.ToCivil(t), time_spec.num_periods) ] return [ DataEntry( data_type=source_calc_type, timestamp=time_util.from_time(timestmap), ) for timestmap in timestamps ]