def test__adjust_number_of_open_positions_2(self, generate_close_orders): """ Test description: - max number of positions is 1 - portfolio contains position with contract ExampleZ00 Comdty - there is a signal with suggested exposure LONG for ExampleN01 Comdty - Expected output: ExampleN01 Comdty suggested exposure will be unchanged """ self.future_ticker.get_current_specific_ticker.return_value = BloombergTicker( "ExampleN01 Comdty") alpha_model_strategy = AlphaModelStrategy( self.ts, {self.alpha_model: [self.future_ticker]}, use_stop_losses=False, max_open_positions=1) self.alpha_model.get_signal.return_value = Signal( self.future_ticker, Exposure.LONG, 1) self.positions_in_portfolio = [ Mock(spec=BacktestPosition, **{ 'contract.return_value': Contract("ExampleZ00 Comdty", "FUT", "SIM_EXCHANGE"), 'quantity.return_value': -10, 'start_time': str_to_date("2000-01-01") }) ] alpha_model_strategy.on_before_market_open() self.ts.position_sizer.size_signals.assert_called_with( [Signal(self.future_ticker, Exposure.LONG, 1)], False)
def _assert_current_prices_are_correct(self, curr_time_str, expected_values): current_time = str_to_date(curr_time_str, DateFormat.FULL_ISO) self.timer.set_current_time(current_time) expected_series = Series(data=expected_values, index=self.tickers) actual_series = self.data_handler.get_current_price(self.tickers) assert_series_equal(expected_series, actual_series, check_names=False)
def test_get_history_when_end_date_is_today_after_market_close(self): self.timer.set_current_time(str_to_date("2018-01-31 21:00:00.000000", DateFormat.FULL_ISO)) prices_tms = self.data_handler.get_history(self.spx_index_ticker, 'PX_TO_BOOK_RATIO', self.start_date, self.end_date) self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime()) self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())
def test__adjust_number_of_open_positions_2(self, generate_close_orders): """ Test description: - max number of positions is 1 - portfolio contains position with contract ExampleZ00 Comdty - there is a signal with suggested exposure LONG for ExampleN01 Comdty - Expected output: ExampleN01 Comdty suggested exposure will be unchanged """ self.future_ticker.ticker = BloombergTicker("ExampleN01 Comdty") alpha_model_strategy = AlphaModelStrategy( self.ts, {self.alpha_model: [self.future_ticker]}, use_stop_losses=False, max_open_positions=1) self.alpha_model.get_signal.return_value = Signal( self.future_ticker, Exposure.LONG, 1, Mock(), Mock()) self.positions_in_portfolio = [ Mock(spec=BacktestPosition, **{ 'ticker.return_value': BloombergTicker("ExampleZ00 Comdty", SecurityType.FUTURE, 1), 'quantity.return_value': -10, 'start_time': str_to_date("2000-01-01") }) ] alpha_model_strategy.calculate_and_place_orders() self.ts.position_sizer.size_signals.assert_called_with( [Signal(self.future_ticker, Exposure.LONG, 1, Mock(), Mock())], False, TimeInForce.OPG, Frequency.DAILY)
def test_get_signals__one_ticker_multiple_signals(self): """ Save signals belonging to one ticker. In this case, even if multiple different signals will be generated for one date, only one of them will be returned (always the first one). """ ticker = BloombergTicker("Example Index") number_of_days = 30 start_date = str_to_date("2000-01-01") end_date = start_date + RelativeDelta(days=number_of_days - 1) signals_register = BacktestSignalsRegister() for date in date_range(start_date, end_date, freq="D"): signals_register.save_signals([Signal(ticker, Exposure.LONG, 0.0)], date) signals_register.save_signals( [Signal(ticker, Exposure.SHORT, 0.0)], date) signals_df = signals_register.get_signals() self.assertEqual(type(signals_df), QFDataFrame) self.assertEqual(signals_df.shape, (number_of_days, 1)) for column, tms in signals_df.iteritems(): self.assertTrue( all(s.suggested_exposure == Exposure.LONG for s in tms))
def test__get_current_exposure__future_ticker_rolling_3( self, generate_close_orders): """ Test the result of _get_current_exposure function for a future ticker in case if a position for an expired contract exists in portfolio and the rolling should be performed. """ # Set the future ticker to point to a new specific ticker, different from the one in the position from portfolio self.future_ticker.ticker = BloombergTicker("ExampleN01 Comdty") futures_alpha_model_strategy = AlphaModelStrategy( self.ts, {self.alpha_model: [self.future_ticker]}, use_stop_losses=False) self.positions_in_portfolio = [ Mock(spec=BacktestPosition, **{ 'ticker.return_value': BloombergTicker("ExampleZ00 Comdty", SecurityType.FUTURE, 1), 'quantity.return_value': -10, 'start_time': str_to_date("2000-01-01") }), Mock(spec=BacktestPosition, **{ 'ticker.return_value': BloombergTicker("ExampleN01 Comdty", SecurityType.FUTURE, 1), 'quantity.return_value': 20, 'start_time': str_to_date("2000-01-02") }), Mock(spec=BacktestPosition, **{ 'ticker.return_value': BloombergTicker("ExampleZ01 Comdty", SecurityType.FUTURE, 1), 'quantity.return_value': 20, 'start_time': str_to_date("2000-01-02") }) ] self.assertRaises( AssertionError, futures_alpha_model_strategy.calculate_and_place_orders)
def test_asof_nans_when_no_data_available(self): actual_result = self.qf_data_array.asof(str_to_date('2018-02-02')) expected_result = pd.DataFrame( index=self.qf_data_array.tickers.to_index(), columns=self.qf_data_array.fields.to_index() ) assert_dataframes_equal(expected_result, actual_result)
def main(): start_date = str_to_date('2018-01-01') initial_value = 1000 portfolio = Portfolio(None, initial_value, None, None) backtest_result = BacktestResult(portfolio, 'Monitor Test', start_date=start_date) backtest_result.start_time = start_date settings = container.resolve(Settings) # type: Settings pdf_exporter = container.resolve(PDFExporter) # type: PDFExporter xlsx_exporter = container.resolve(ExcelExporter) # type: ExcelExporter monitor = BacktestMonitor(backtest_result, settings, pdf_exporter, xlsx_exporter) # put first point # noinspection PyProtectedMember portfolio.dates.append(start_date) # noinspection PyProtectedMember portfolio.portfolio_values.append(initial_value) # create an Transaction timestamp = str_to_date("2010-01-01") contract = Contract("MSFT US Equity", security_type="STK", exchange="NYSE") quantity = 13 price = 100.5 commission = 1.2 transaction = Transaction(timestamp, contract, quantity, price, commission) for i in range(50): date = start_date + timedelta(days=i) # noinspection PyProtectedMember past_value = portfolio.portfolio_values[-1] rand = randint(0, 100) - 50 # noinspection PyProtectedMember portfolio.dates.append(date) # noinspection PyProtectedMember portfolio.portfolio_values.append(past_value + rand) monitor.end_of_day_update(date) monitor.record_transaction(transaction) time.sleep(0.1) monitor.end_of_trading_update()
def test_get_price_single_ticker_many_fields_single_date(self): date = str_to_date('2021-06-11') data_provider = self.get_data_provider(self.ticker, self.fields) prices = data_provider.get_price(self.ticker, self.fields, date, date) self.assertEqual(type(prices), PricesSeries) self.assertEqual(prices.shape, (len(self.fields), ))
def test_valid_ticker_2(self): # Test the 2nd contract instead of front one future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 2, 5, 500) future_ticker.initialize_data_provider(self.timer, self.bbg_provider) self.timer.set_current_time(str_to_date('2017-12-05')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("C")) self.timer.set_current_time(str_to_date('2017-12-10')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("C")) self.timer.set_current_time(str_to_date('2017-12-11')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("D"))
def setUpClass(cls): cls.start_date = str_to_date("2017-10-01") cls.end_date = str_to_date("2017-11-01") cls.frequency = Frequency.DAILY datetime_index = pd.DatetimeIndex([ '2017-10-02', '2017-10-03', '2017-10-04', '2017-10-05', '2017-10-06', '2017-10-09', '2017-10-10', '2017-10-11', '2017-10-12', '2017-10-13', '2017-10-16', '2017-10-17', '2017-10-18', '2017-10-19', '2017-10-20', '2017-10-23', '2017-10-24', '2017-10-25', '2017-10-26', '2017-10-27', '2017-10-30', '2017-10-31', '2017-11-01' ]) bbg_data_provider = Mock(spec=BloombergDataProvider) all_tickers_str = ['BCIT3T Index', 'IEF US Equity', 'LQD US Equity', 'MSBIERTR Index', 'MXUS Index', 'SPGSCITR Index', 'XAU Curncy'] all_tickers = BloombergTicker.from_string(all_tickers_str) assets_prices_df = PricesDataFrame(index=datetime_index, columns=all_tickers, data=[ [263.7628, 106.24, 121.02, 321.8249, 2409.48, 2295.60, 1271.13], [263.9803, 106.39, 121.29, 322.0949, 2414.41, 2294.91, 1271.66], [264.1640, 106.36, 121.22, 322.3203, 2417.31, 2294.28, 1274.85], [264.0932, 106.25, 121.05, 322.4172, 2430.80, 2323.34, 1268.22], [263.9816, 106.12, 120.95, 322.1411, 2428.16, 2282.24, 1276.68], [263.9816, 106.24, 121.05, None, 2423.41, 2284.78, 1284.05], [264.4529, 106.28, 121.13, 322.3113, 2428.73, 2318.99, 1288.03], [264.5108, 106.40, 121.07, 322.3553, 2433.09, 2324.63, 1291.72], [264.8223, 106.50, 121.10, 322.7489, 2428.89, 2314.78, 1293.72], [264.9401, 106.86, 121.58, 322.8720, 2430.63, 2342.19, 1303.82], [264.2089, 106.68, 121.41, 322.8467, 2434.66, 2353.20, 1295.79], [264.0592, 106.64, 121.39, 323.1079, 2436.35, 2345.04, 1285.12], [263.9370, 106.37, 121.21, 323.2238, 2438.08, 2345.57, 1281.08], [264.0463, 106.48, 121.39, 323.5498, 2439.31, 2332.31, 1290.13], [263.8424, 106.04, 121.06, 322.9874, 2451.70, 2340.26, 1280.47], [263.8961, 106.14, 121.18, 322.7436, 2441.71, 2343.72, 1282.27], [263.7129, 105.82, 120.88, 322.3214, 2445.61, 2366.00, 1276.58], [263.3216, 105.65, 120.56, 322.4332, 2434.13, 2364.23, 1277.53], [263.3638, 105.51, 120.55, 322.1635, 2438.07, 2376.52, 1266.99], [263.8662, 105.85, 120.91, 322.3655, 2457.45, 2396.93, 1273.35], [264.4531, 106.23, 121.31, 322.9710, 2449.20, 2407.43, 1276.29], [264.4690, 106.16, 121.14, 323.0688, 2452.15, 2415.28, 1271.45], [264.4727, 106.06, 121.01, 323.1553, 2455.70, 2415.48, 1274.66] ]) bbg_data_provider.get_price.return_value = assets_prices_df cls.bbg_data_provider = bbg_data_provider
def test_valid_ticker_4(self): future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 2, 45, 500) future_ticker.initialize_data_provider(self.timer, self.bbg_provider) self.timer.set_current_time(str_to_date('2017-11-28')) # '2017-11-28' + 45 days = '2018-01-12' - the front contract will be equal to CustomTicker:D self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("D")) self.timer.set_current_time(str_to_date('2017-11-29')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("E")) self.timer.set_current_time(str_to_date('2017-12-05')) # '2017-12-05' + 45 days = '2018-01-19' - the front contract will be equal to CustomTicker:D self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("E"))
def main(): # settings backtest_name = 'Simple MA Strategy Demo' start_date = str_to_date("2010-01-01") end_date = str_to_date("2015-03-01") ticker = DummyTicker("AAA") # configuration session_builder = container.resolve(BacktestTradingSessionBuilder) # type: BacktestTradingSessionBuilder session_builder.set_frequency(Frequency.DAILY) session_builder.set_backtest_name(backtest_name) session_builder.set_data_provider(daily_data_provider) ts = session_builder.build(start_date, end_date) OnBeforeMarketOpenSignalGeneration(SimpleMAStrategy(ts, ticker)) ts.start_trading()
def main(): initial_risk = 0.03 start_date = str_to_date('2010-01-01') end_date = str_to_date('2011-12-31') # Use the preset daily data provider data_provider = daily_data_provider # ----- build trading session ----- # session_builder = container.resolve( BacktestTradingSessionBuilder) # type: BacktestTradingSessionBuilder session_builder.set_backtest_name('Moving Average Alpha Model Backtest') session_builder.set_position_sizer(InitialRiskPositionSizer, initial_risk=initial_risk) session_builder.set_contract_ticker_mapper(DummyTickerMapper()) session_builder.set_commission_model(IBCommissionModel) session_builder.set_data_provider(data_provider) session_builder.set_frequency(Frequency.DAILY) ts = session_builder.build(start_date, end_date) # ----- build models ----- # model = MovingAverageAlphaModel(fast_time_period=5, slow_time_period=20, risk_estimation_factor=1.25, data_handler=ts.data_handler) model_tickers = [ DummyTicker('AAA'), DummyTicker('BBB'), DummyTicker('CCC'), DummyTicker('DDD'), DummyTicker('EEE'), DummyTicker('FFF') ] model_tickers_dict = {model: model_tickers} # ----- preload price data ----- # ts.use_data_preloading(model_tickers) # Verify the checksum of preloaded data with the precomputed value ts.verify_preloaded_data("778bbaac65cb0a5a848167999b88cf29a1cd8467") # ----- start trading ----- # AlphaModelStrategy(ts, model_tickers_dict, use_stop_losses=True) ts.start_trading()
def test_get_last_price_single_ticker(self): # just test if getting single ticker value works, when a single ticker (not wrapped in a list) is passed self.timer.set_current_time( str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() + RelativeDelta(hours=1)) single_price = self.data_handler.get_last_available_price( self.spx_index_ticker) self.assertTrue(isinstance(single_price, float)) # during the trading session self.timer.set_current_time( str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() + RelativeDelta(hours=1)) during_the_day_last_prices = self.data_handler.get_last_available_price( [self.spx_index_ticker]) self.assertEqual(self.spx_index_ticker, during_the_day_last_prices.index[0]) self.assertEqual(single_price, during_the_day_last_prices[0]) # after the trading session self.timer.set_current_time( str_to_date("2018-01-31") + MarketCloseEvent.trigger_time() + RelativeDelta(hours=1)) after_close_last_prices = self.data_handler.get_last_available_price( [self.spx_index_ticker]) self.assertEqual(self.spx_index_ticker, after_close_last_prices.index[0]) self.assertNotEqual(during_the_day_last_prices[0], after_close_last_prices[0]) # before the trading session self.timer.set_current_time( str_to_date("2018-01-31") + MarketOpenEvent.trigger_time() - RelativeDelta(hours=1)) before_close_last_prices = self.data_handler.get_last_available_price( [self.spx_index_ticker]) self.assertEqual(self.spx_index_ticker, before_close_last_prices.index[0]) self.assertNotEqual(during_the_day_last_prices[0], before_close_last_prices[0]) self.assertNotEqual(after_close_last_prices[0], before_close_last_prices[0])
def test_valid_ticker_1(self): future_ticker = CustomFutureTicker("Custom", "CT{} Custom", 1, 5, 500) future_ticker.initialize_data_provider(self.timer, self.bbg_provider) # '2017-12-15' is the official expiration date of CustomTicker:B, setting the days_before_exp_date equal to # 5 forces the expiration to occur on the 11th ('2017-12-15' - 5 days = '2017-12-10' is the last day of old # contract). self.timer.set_current_time(str_to_date('2017-12-05')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("B")) self.timer.set_current_time(str_to_date('2017-12-10')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("B")) self.timer.set_current_time(str_to_date('2017-12-11')) self.assertEqual(future_ticker.get_current_specific_ticker(), CustomTicker("C"))
def setUpClass(cls) -> None: cls.end_date = str_to_date('2015-10-08') cls.start_date = cls.end_date - RelativeDelta(years=2) cls.timer = SettableTimer(cls.end_date) cls.frequency = Frequency.DAILY cls.TICKER_1 = BloombergFutureTicker("Cotton", "CT{} Comdty", 1, 3) cls.TICKER_2 = BloombergFutureTicker("Corn", 'C {} Comdty', 1, 5)
def _setup_data_handler(self, volume_value: Optional[float]) -> DataHandler: dates = pd.date_range(str_to_date("2020-01-01"), str_to_date("2020-01-30"), freq='D') prices_data_frame = QFDataFrame( data={PriceField.Volume: [volume_value] * len(dates)}, index=dates) prices_data_array = tickers_dict_to_data_array( { self.ticker: prices_data_frame, }, [self.ticker], [PriceField.Volume]) data_provider = PresetDataProvider(prices_data_array, dates[0], dates[-1], Frequency.DAILY) timer = SettableTimer(dates[-1]) return DailyDataHandler(data_provider, timer)
def _assert_last_prices_are_correct(self, curr_time_str, expected_values, frequency): current_time = str_to_date(curr_time_str, DateFormat.FULL_ISO) self.current_time = current_time expected_series = QFSeries(data=expected_values, index=[self.ticker_1, self.ticker_2]) actual_series = self.data_provider.get_last_available_price( [self.ticker_1, self.ticker_2], frequency) assert_series_equal(expected_series, actual_series, check_names=False)
def test_get_price_when_end_date_is_in_the_past(self): self.timer.set_current_time( str_to_date("2018-02-12 00:00:00.000000", DateFormat.FULL_ISO)) prices_tms = self.data_handler.get_price(self.spx_index_ticker, PriceField.Close, self.start_date, self.end_date) self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime()) self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())
def test_get_last_price_with_multiple_tickers_when_current_data_is_unavailable( self): self.timer.set_current_time( str_to_date("2018-01-01") + MarketOpenEvent.trigger_time() + RelativeDelta(hours=1)) last_prices = self.data_handler.get_last_available_price( [self.spx_index_ticker, self.google_ticker]) self.assertEqual(self.spx_index_ticker, last_prices.index[0]) self.assertEqual(self.google_ticker, last_prices.index[1])
def _assert_last_price_is_correct(self, curr_time_str, ticker, expected_value, frequency): current_time = str_to_date(curr_time_str, DateFormat.FULL_ISO) self.current_time = current_time actual_value = self.data_provider.get_last_available_price( ticker, frequency) if isnan(expected_value): self.assertTrue(isnan(actual_value)) else: self.assertEqual(expected_value, actual_value)
def setUpClass(cls): cls.start_date = str_to_date('2008-10-08') cls.end_date = str_to_date('2018-12-20') cls.timer = SettableTimer() cls.timer.set_current_time(cls.end_date) cls.frequency = Frequency.DAILY cls.ticker_1 = BloombergFutureTicker("Euroswiss", "ES{} Index", 1, 3, 100, "HMUZ") cls.ticker_2 = BloombergFutureTicker("Corn", "C {} Comdty", 1, 3, 100, "HKNUZ") MarketCloseEvent.set_trigger_time({ "hour": 20, "minute": 00, "second": 0, "microsecond": 0 })
def test_get_history_with_multiple_tickers(self): self.timer.set_current_time(str_to_date("2018-01-31 12:00:00.000000", DateFormat.FULL_ISO)) resilt_df = self.data_handler.get_history([self.microsoft_ticker, self.google_ticker], 'PX_TO_BOOK_RATIO', self.start_date, self.end_date_trimmed) self.assertEqual(self.microsoft_ticker, resilt_df.columns[0]) self.assertEqual(self.google_ticker, resilt_df.columns[1]) self.assertEqual(self.start_date, resilt_df.index[0].to_pydatetime()) self.assertEqual(self.end_date_trimmed, resilt_df.index[-1].to_pydatetime()) self.assertEqual(resilt_df.shape, (20, 2))
def _assert_bars_for_today_is_correct(self, curr_time_str, expected_values): current_time = str_to_date(curr_time_str, DateFormat.FULL_ISO) self.timer.set_current_time(current_time) expected_dataframe = QFDataFrame(data=expected_values, index=self.tickers_index, columns=self.fields_index) actual_dataframe = self.data_handler.get_current_bar(self.tickers) assert_dataframes_equal(expected_dataframe, actual_dataframe, check_names=False)
def get_data(): data_provider = container.resolve( QuandlDataProvider) # type: QuandlDataProvider start_date = str_to_date('2010-01-01') end_date = str_to_date('2017-12-31') live_date = str_to_date('2015-01-01') strategy = data_provider.get_price(tickers=QuandlTicker('AAPL', 'WIKI'), fields=PriceField.Close, start_date=start_date, end_date=end_date) benchmark = data_provider.get_price(tickers=QuandlTicker('IBM', 'WIKI'), fields=PriceField.Close, start_date=start_date, end_date=end_date) strategy.name = "Strategy" benchmark.name = "Benchmark" return strategy, benchmark, live_date
def test_get_price_when_end_date_is_today_after_market_close(self): self.timer.set_current_time( str_to_date("2018-01-31") + MarketCloseEvent.trigger_time() + RelativeDelta(hours=1)) prices_tms = self.data_handler.get_price(self.spx_index_ticker, PriceField.Close, self.start_date, self.end_date) self.assertEqual(self.start_date, prices_tms.index[0].to_pydatetime()) self.assertEqual(self.end_date, prices_tms.index[-1].to_pydatetime())
def test_correct_time_event_is_returned(self): self.timer.set_current_time(str_to_date("2018-01-01")) listener = Mock() another_listener = Mock() self.scheduler.subscribe(self._CustomTimeEvent, listener) self.scheduler.subscribe(self._AnotherCustomTimeEvent, another_listener) actual_time_events_list, time = self.scheduler.get_next_time_events() expected_time_event = self._CustomTimeEvent() self.assertIn(expected_time_event, actual_time_events_list) self.timer.set_current_time(str_to_date("2018-01-03")) another_actual_time_events_list, time = self.scheduler.get_next_time_events( ) another_expected_time_event = self._AnotherCustomTimeEvent() self.assertIn(another_expected_time_event, another_actual_time_events_list)
def setUp(self): try: self.data_provider = get_data_provider() except Exception as e: raise self.skipTest(e) self.ticker_1.initialize_data_provider(self.timer, self.data_provider) self.ticker_2.initialize_data_provider(self.timer, self.data_provider) self.timer.set_current_time( str_to_date("2017-12-20 00:00:00.000000", DateFormat.FULL_ISO))
def test_fixed_slippage__nan_prices(self): slippage_per_share = 0.1 slippage_model = FixedSlippage(slippage_per_share, self.data_provider, self.contract_ticker_mapper) prices_without_slippage = [float('nan'), np.nan, float('nan')] expected_fill_prices = [float('nan'), float('nan'), float('nan')] actual_fill_prices, actual_fill_volumes = slippage_model.process_orders(str_to_date("2020-01-01"), self.orders, prices_without_slippage) assert_lists_equal(expected_fill_prices, actual_fill_prices)