def test_can_load_full_ohlc_from_partials(self): instr = m.FXInstrument("i") ohlc1 = OHLC(date(2005, 6, 20), open=10.0, low=5.0, high=15.0, close=12.0, num_trades=1, volume=100.0, waprice=11.0) ohlc2 = OHLC(date(2005, 6, 23), open=10.0, low=5.0, high=15.0, close=13.0, num_trades=2, volume=100.0, waprice=11.0) partial_replies = [ OHLCSeries(instr.code, [ohlc1]), OHLCSeries(instr.code, [ohlc2]), OHLCSeries(instr.code, []) ] mocked_loader = MagicMock(side_effect=partial_replies) full_table = instr.load_ohlc_table(None, mocked_loader) assert not full_table.is_empty() assert full_table.ohlc_series == [ohlc1, ohlc2]
def test_csv_parse_unparse(self): ohlc = OHLC(date.today(), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=12.0) csv_row = ohlc.to_csv_row() ohlc_parsed = OHLC.from_csv_row(csv_row) assert ohlc == ohlc_parsed
def _parse_ohlc_csv(self, reply: str) -> OHLCSeries: lines = reply.split("\n")[2:] # note field names in moex reply are OLHC (parsed here), but our native csv # (in instruments module) is OHLC as market convention reader = csv.DictReader(lines, delimiter=";") series = [] name = None for row in reader: try: num_trades = self.parse_num_trades(row) date = datetime.date.fromisoformat(row["TRADEDATE"]) if num_trades != 0: ohlc = OHLC(date=date, open=float(row["OPEN"]), low=float(row["LOW"]), high=float(row["HIGH"]), close=float(row["CLOSE"]), num_trades=num_trades, volume=self.parse_volume(row), waprice=self.parse_waprice(row)) series.append(ohlc) else: # otherwise pandas import will change column type from double to object due to NA presence logger.info( f"Skipping {date} for {self} as it had no trades") if name is None: name = row["SHORTNAME"] except ValueError as e: raise ValueError(f"Error happened for row {row}", e) if self.name is None: self.name = name return OHLCSeries(self.code, series, name)
def test_can_create_ohlc_with_waprice_not_within_high_and_low(self): OHLC(date.today(), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=90.0)
def test_cannot_create_ohlc_with_close_not_within_high_and_low(self): with pytest.raises(ValueError): OHLC(date.today(), open=10.0, low=9.0, high=15.0, close=16.0, num_trades=1, volume=10.0, waprice=9.0)
def test_cannot_create_ohlc_with_low_greater_than_high(self): with pytest.raises(ValueError): OHLC(date.today(), open=10.0, low=9.0, high=8.0, close=11.0, num_trades=1, volume=10.0, waprice=9.0)
def test_can_create_good_instance(self): series = OHLCSeries("instr", [ OHLC(date(2020, 12, 4), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), OHLC(date(2020, 12, 5), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), ]) assert not series.is_empty()
def test_cannot_create_with_dates_not_ascending(self): with pytest.raises(ValueError): OHLCSeries("instr", [ OHLC(date(2020, 12, 5), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), OHLC(date(2020, 12, 4), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0) ])
def test_can_grow_series(self): series1 = OHLCSeries("instr", [ OHLC(date(2020, 12, 4), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), OHLC(date(2020, 12, 5), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), ]) series2 = OHLCSeries("instr", [ OHLC(date(2020, 12, 6), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), OHLC(date(2020, 12, 7), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), ]) series1.append(series2) assert len(series1.ohlc_series) == 4 assert series1.ohlc_series[2:] == series2.ohlc_series
def test_cannot_append_non_adjacent_series(self): with pytest.raises(ValueError) as e: series1 = OHLCSeries("instr", [ OHLC(date(2020, 12, 4), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), OHLC(date(2020, 12, 5), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), ]) series2 = OHLCSeries("instr", [ OHLC(date(2020, 12, 5), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), OHLC(date(2020, 12, 6), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0), ]) series1.append(series2) assert "First date (2020-12-05) must be > 2020-12-05" in str(e.value)
def test_can_parse_currency_ohlc(self, sample_ohlc_currency_csv): inst = m.FXInstrument("eurrub") ohlc: OHLCSeries = inst._parse_ohlc_csv(sample_ohlc_currency_csv) assert not ohlc.is_empty() s = ohlc.ohlc_series assert s[0] == OHLC(date(2005, 6, 20), open=34.79, low=34.7701, high=34.83, close=34.81, num_trades=21, volume=157224489.9, waprice=34.8073) assert s[-1] == OHLC(date(2005, 11, 7), open=34.97, low=33.925, high=34.97, close=34.01, num_trades=57, volume=142336864.5, waprice=34.0031) assert ohlc.name == "EURRUB_TOM" assert inst.name == ohlc.name
def test_can_parse_index_ohlc(self, sample_ohlc_index_csv): inst = m.IndexInstrument("mredc") assert inst.name is None ohlc: OHLCSeries = inst._parse_ohlc_csv(sample_ohlc_index_csv) assert not ohlc.is_empty() s = ohlc.ohlc_series assert s[0] == OHLC(date(2016, 12, 28), open=159646.69, low=159646.69, high=159646.69, close=159646.69, num_trades=1, volume=0.0, waprice=0.0) assert s[-1] == OHLC(date(2018, 11, 21), open=167319.51, low=167319.51, high=167319.51, close=167319.51, num_trades=1, volume=0.0, waprice=0.0) assert ohlc.name == "Индекс недвиж-ти ДомКлик Москва" assert inst.name == ohlc.name
def test_avg_of_last_elems(self): close = [1.0, 2.0, 3.0, 4.0] open = [2.0, 3.0, 4.0, 5.0] ohlcs = [ OHLC(date(2021, 1, 1) + timedelta(days=i), open=open[i], low=0.0, high=10.0, close=close[i], num_trades=1, volume=1.0, waprice=1.0) for i in range(len(close)) ] series = OHLCSeries("i", ohlcs) assert series.mean_of_last_elems(2) == (close[-2] + close[-1]) / 2 assert series.mean_of_last_elems( 2, lambda ohlc: ohlc.open) == (open[-2] + open[-1]) / 2 assert series.mean_of_last_elems(4) == (close[0] + close[1] + close[2] + close[3]) / 4 with pytest.raises(ValueError): series.mean_of_last_elems(5)
def test_empty_processing(self): s1 = OHLCSeries("i", []) s1.append(OHLCSeries("i", [])) assert s1.is_empty() s_tmp = OHLCSeries("i", [ OHLC(date(2020, 12, 6), open=9.0, low=9.0, high=15.0, close=11.0, num_trades=1, volume=10.0, waprice=13.0) ]) s2 = OHLCSeries("i", []) s2.append(s_tmp) assert not s2.is_empty() assert s2 == s_tmp s_tmp.append(OHLCSeries("i", [])) assert not s_tmp.is_empty()