def setup(self):
        # Fixture Setup
        config = BacktestEngineConfig(
            bypass_logging=False,
            run_analysis=False,
            cache_database=CacheDatabaseConfig(),  # default redis
            cache_db_flush=False,
        )

        self.engine = BacktestEngine(config=config)

        self.usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")

        wrangler = QuoteTickDataWrangler(self.usdjpy)
        provider = TestDataProvider()
        ticks = wrangler.process_bar_data(
            bid_data=provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv"),
            ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv"),
        )
        self.engine.add_instrument(self.usdjpy)
        self.engine.add_ticks(ticks)

        self.engine.add_venue(
            venue=Venue("SIM"),
            oms_type=OMSType.HEDGING,
            account_type=AccountType.MARGIN,
            base_currency=USD,
            starting_balances=[Money(1_000_000, USD)],
            modules=[],
        )

        self.test_redis = redis.Redis(host="localhost", port=6379, db=0)
    def setup(self):
        # Fixture Setup
        config = BacktestEngineConfig(
            bypass_logging=True,
            run_analysis=False,
        )
        self.engine = BacktestEngine(config=config)

        self.usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")

        # Setup data
        wrangler = QuoteTickDataWrangler(self.usdjpy)
        provider = TestDataProvider()
        ticks = wrangler.process_bar_data(
            bid_data=provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv"),
            ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv"),
        )
        self.engine.add_instrument(self.usdjpy)
        self.engine.add_ticks(ticks)

        self.engine.add_venue(
            venue=Venue("SIM"),
            venue_type=VenueType.BROKERAGE,
            oms_type=OMSType.HEDGING,
            account_type=AccountType.MARGIN,
            base_currency=USD,
            starting_balances=[Money(1_000_000, USD)],
            modules=[],
        )
Пример #3
0
    def setup(self):
        # Fixture Setup
        self.engine = BacktestEngine()

        self.usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")

        # Setup data
        wrangler = QuoteTickDataWrangler(self.usdjpy)
        provider = TestDataProvider()
        ticks = wrangler.process_bar_data(
            bid_data=provider.read_csv_bars(
                "fxcm-usdjpy-m1-bid-2013.csv")[:2000],
            ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv")
            [:2000],
        )
        self.engine.add_instrument(USDJPY_SIM)
        self.engine.add_ticks(ticks)

        self.engine.add_venue(
            venue=Venue("SIM"),
            oms_type=OMSType.HEDGING,
            account_type=AccountType.MARGIN,
            base_currency=USD,
            starting_balances=[Money(1_000_000, USD)],
            fill_model=FillModel(),
        )
Пример #4
0
    def setup(self):
        # Fixture Setup
        config = BacktestEngineConfig(
            bypass_logging=True,
            run_analysis=False,
        )
        self.engine = BacktestEngine(config=config)

        self.venue = Venue("SIM")
        self.usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")

        # Setup data
        wrangler = QuoteTickDataWrangler(instrument=self.usdjpy)
        provider = TestDataProvider()
        ticks = wrangler.process_bar_data(
            bid_data=provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv"),
            ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv"),
        )
        self.engine.add_instrument(self.usdjpy)
        self.engine.add_ticks(ticks)

        interest_rate_data = pd.read_csv(
            os.path.join(PACKAGE_ROOT, "data", "short-term-interest.csv"))
        fx_rollover_interest = FXRolloverInterestModule(
            rate_data=interest_rate_data)

        self.engine.add_venue(
            venue=self.venue,
            oms_type=OMSType.HEDGING,
            account_type=AccountType.MARGIN,
            base_currency=USD,
            starting_balances=[Money(1_000_000, USD)],
            modules=[fx_rollover_interest],
        )
        def setup():
            config = BacktestEngineConfig(bypass_logging=True)
            engine = BacktestEngine(config=config)

            # Setup data
            wrangler = QuoteTickDataWrangler(USDJPY_SIM)
            provider = TestDataProvider()
            ticks = wrangler.process_bar_data(
                bid_data=provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv"),
                ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv"),
            )
            engine.add_instrument(USDJPY_SIM)
            engine.add_ticks(ticks)

            engine.add_venue(
                venue=Venue("SIM"),
                oms_type=OMSType.HEDGING,
                account_type=AccountType.MARGIN,
                base_currency=USD,
                starting_balances=[Money(1_000_000, USD)],
            )

            config = EMACrossConfig(
                instrument_id=str(USDJPY_SIM.id),
                bar_type=str(TestDataStubs.bartype_usdjpy_1min_bid()),
                trade_size=Decimal(1_000_000),
                fast_ema=10,
                slow_ema=20,
            )
            strategy = EMACross(config=config)

            start = datetime(2013, 2, 1, 0, 0, 0, 0, tzinfo=pytz.utc)
            end = datetime(2013, 2, 10, 0, 0, 0, 0, tzinfo=pytz.utc)

            return (engine, start, end, strategy), {}
    def test_pre_process_bar_data_with_random_seed(self):
        # Arrange
        usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")
        provider = TestDataProvider()
        bid_data = provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv")[:100]
        ask_data = provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv")[:100]

        wrangler = QuoteTickDataWrangler(instrument=usdjpy)

        # Act
        ticks = wrangler.process_bar_data(
            bid_data=bid_data,
            ask_data=ask_data,
            default_volume=1000000,
            random_seed=42,  # <-- with random seed
        )

        # Assert
        assert ticks[0].bid == Price.from_str("91.715")
        assert ticks[0].ask == Price.from_str("91.717")
        assert ticks[1].bid == Price.from_str("91.653")
        assert ticks[1].ask == Price.from_str("91.655")
        assert ticks[2].bid == Price.from_str("91.715")
        assert ticks[2].ask == Price.from_str("91.717")
        assert ticks[3].bid == Price.from_str("91.653")
        assert ticks[3].ask == Price.from_str("91.655")
    def test_pre_process_bar_data_with_delta(self):
        # Arrange
        usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")
        provider = TestDataProvider()
        bid_data = provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv")[:100]
        ask_data = provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv")[:100]

        wrangler = QuoteTickDataWrangler(instrument=usdjpy)

        # Act
        ticks = wrangler.process_bar_data(
            bid_data=bid_data,
            ask_data=ask_data,
            default_volume=1000000,
            ts_init_delta=1_000_500,
        )

        # Assert
        assert len(ticks) == 400
        assert ticks[0].instrument_id == usdjpy.id
        assert ticks[0].bid == Price.from_str("91.715")
        assert ticks[0].ask == Price.from_str("91.717")
        assert ticks[0].bid_size == Quantity.from_int(1000000)
        assert ticks[0].ask_size == Quantity.from_int(1000000)
        assert ticks[0].ts_event == 1359676799700000000
        assert ticks[0].ts_init == 1359676799701000500  # <-- delta diff
Пример #8
0
    def setup(self):
        # Fixture Setup
        config = BacktestEngineConfig(
            bypass_logging=True,
            run_analysis=False,
        )
        self.engine = BacktestEngine(config=config)

        self.venue = Venue("SIM")
        self.audusd = TestInstrumentProvider.default_fx_ccy("AUD/USD")

        # Setup data
        wrangler = QuoteTickDataWrangler(self.audusd)
        provider = TestDataProvider()
        ticks = wrangler.process(
            provider.read_csv_ticks("truefx-audusd-ticks.csv"))
        self.engine.add_instrument(self.audusd)
        self.engine.add_ticks(ticks)

        interest_rate_data = provider.read_csv("short-term-interest.csv")
        fx_rollover_interest = FXRolloverInterestModule(
            rate_data=interest_rate_data)

        self.engine.add_venue(
            venue=Venue("SIM"),
            oms_type=OMSType.HEDGING,
            account_type=AccountType.MARGIN,
            base_currency=AUD,
            starting_balances=[Money(1_000_000, AUD)],
            modules=[fx_rollover_interest],
        )
    def test_run_quote_ticks_through_aggregator_results_in_expected_bars(self):
        # Arrange
        bar_store = ObjectStorer()
        handler = bar_store.store
        instrument = AUDUSD_SIM
        bar_spec = BarSpecification(1000, BarAggregation.VOLUME, PriceType.MID)
        bar_type = BarType(instrument.id, bar_spec)
        aggregator = VolumeBarAggregator(
            instrument,
            bar_type,
            handler,
            Logger(TestClock()),
        )

        # Setup data
        wrangler = QuoteTickDataWrangler(instrument)
        provider = TestDataProvider()
        ticks = wrangler.process(
            data=provider.read_csv_ticks("truefx-audusd-ticks.csv")[:10000],
            default_volume=1,
        )

        # Act
        for tick in ticks:
            aggregator.handle_quote_tick(tick)

        # Assert
        last_bar = bar_store.get_store()[-1]
        assert len(bar_store.get_store()) == 10
        assert last_bar.open == Price.from_str("0.670635")
        assert last_bar.high == Price.from_str("0.670705")
        assert last_bar.low == Price.from_str("0.670370")
        assert last_bar.close == Price.from_str("0.670655")
        assert last_bar.volume == Quantity.from_int(1000)
Пример #10
0
        def setup():
            # Arrange
            config = BacktestEngineConfig(bypass_logging=True)
            engine = BacktestEngine(config=config)

            # Setup data
            wrangler = QuoteTickDataWrangler(USDJPY_SIM)
            provider = TestDataProvider()
            ticks = wrangler.process_bar_data(
                bid_data=provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv"),
                ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv"),
            )
            engine.add_instrument(USDJPY_SIM)
            engine.add_ticks(ticks)

            engine.add_venue(
                venue=Venue("SIM"),
                venue_type=VenueType.BROKERAGE,
                oms_type=OMSType.HEDGING,
                account_type=AccountType.MARGIN,
                base_currency=USD,
                starting_balances=[Money(1_000_000, USD)],
                fill_model=FillModel(),
            )
            strategies = [TradingStrategy()]
            start = datetime(2013, 1, 1, 22, 0, 0, 0, tzinfo=pytz.utc)
            end = datetime(2013, 8, 10, 0, 0, 0, 0, tzinfo=pytz.utc)
            return (engine, start, end, strategies), {}
Пример #11
0
 def parser(data):
     if data is None:
         return
     data.loc[:, "timestamp"] = pd.to_datetime(data["timestamp"])
     instrument = TestInstrumentProvider.default_fx_ccy("AUD/USD")
     wrangler = QuoteTickDataWrangler(instrument)
     ticks = wrangler.process(data.set_index("timestamp"))
     yield from ticks
Пример #12
0
    def test_add_quote_ticks_adds_to_engine(self, capsys):
        # Arrange
        engine = BacktestEngine()

        # Setup data
        engine.add_instrument(AUDUSD_SIM)
        wrangler = QuoteTickDataWrangler(AUDUSD_SIM)
        provider = TestDataProvider()
        ticks = wrangler.process(
            provider.read_csv_ticks("truefx-audusd-ticks.csv"))

        # Act
        engine.add_ticks(ticks)

        # Assert
        log = "".join(capsys.readouterr())
        assert "Added 100,000 AUD/USD.SIM QuoteTick elements." in log
Пример #13
0
        def setup():
            config = BacktestEngineConfig(bypass_logging=True)
            engine = BacktestEngine(config=config)

            # Setup data
            wrangler = QuoteTickDataWrangler(USDJPY_SIM)
            provider = TestDataProvider()
            ticks = wrangler.process_bar_data(
                bid_data=provider.read_csv_bars("fxcm-usdjpy-m1-bid-2013.csv"),
                ask_data=provider.read_csv_bars("fxcm-usdjpy-m1-ask-2013.csv"),
            )
            engine.add_instrument(USDJPY_SIM)
            engine.add_ticks(ticks)

            interest_rate_data = pd.read_csv(
                os.path.join(PACKAGE_ROOT, "data", "short-term-interest.csv"))
            fx_rollover_interest = FXRolloverInterestModule(
                rate_data=interest_rate_data)

            engine.add_venue(
                venue=Venue("SIM"),
                venue_type=VenueType.BROKERAGE,
                oms_type=OMSType.HEDGING,
                account_type=AccountType.MARGIN,
                base_currency=USD,
                starting_balances=[Money(1_000_000, USD)],
                modules=[fx_rollover_interest],
            )

            config = EMACrossConfig(
                instrument_id=str(USDJPY_SIM.id),
                bar_type=str(TestStubs.bartype_usdjpy_1min_bid()),
                trade_size=Decimal(1_000_000),
                fast_ema=10,
                slow_ema=20,
            )
            strategy = EMACross(config=config)

            start = datetime(2013, 2, 1, 0, 0, 0, 0, tzinfo=pytz.utc)
            end = datetime(2013, 3, 1, 0, 0, 0, 0, tzinfo=pytz.utc)

            return (engine, start, end, [strategy]), {}
    def test_pre_process_with_tick_data(self):
        # Arrange
        instrument = TestInstrumentProvider.btcusdt_binance()
        wrangler = QuoteTickDataWrangler(instrument=instrument)
        path = os.path.join(PACKAGE_ROOT, "data", "tardis_quotes.csv")
        data = TardisQuoteDataLoader.load(path)

        # Act
        ticks = wrangler.process(
            data,
            ts_init_delta=1_000_501,
        )

        # Assert
        assert len(ticks) == 9999
        assert ticks[0].bid == Price.from_str("9681.92")
        assert ticks[0].ask == Price.from_str("9682.00")
        assert ticks[0].bid_size == Quantity.from_str("0.670000")
        assert ticks[0].ask_size == Quantity.from_str("0.840000")
        assert ticks[0].ts_event == 1582329603502091776
        assert ticks[0].ts_init == 1582329603503092277
    def test_process_tick_data(self):
        # Arrange
        usdjpy = TestInstrumentProvider.default_fx_ccy("USD/JPY")

        wrangler = QuoteTickDataWrangler(instrument=usdjpy)
        provider = TestDataProvider()

        # Act
        ticks = wrangler.process(
            data=provider.read_csv_ticks("truefx-usdjpy-ticks.csv"),
            default_volume=1000000,
        )

        # Assert
        assert len(ticks) == 1000
        assert ticks[0].instrument_id == usdjpy.id
        assert ticks[0].bid == Price.from_str("86.655")
        assert ticks[0].ask == Price.from_str("86.728")
        assert ticks[0].bid_size == Quantity.from_int(1000000)
        assert ticks[0].ask_size == Quantity.from_int(1000000)
        assert ticks[0].ts_event == 1357077600295000064
        assert ticks[0].ts_event == 1357077600295000064
Пример #16
0
    def test_run_ema_cross_with_trade_ticks_from_bar_data(self):
        # Arrange
        wrangler = QuoteTickDataWrangler(instrument=self.btcusdt)

        provider = TestDataProvider()

        # Build ticks from bar data
        ticks = wrangler.process_bar_data(
            bid_data=provider.read_csv_bars(
                "ftx-btc-perp-20211231-20220201_1m.csv")[:10000],
            ask_data=provider.read_csv_bars(
                "ftx-btc-perp-20211231-20220201_1m.csv")[:10000],
        )

        self.engine.add_ticks(ticks)

        config = EMACrossConfig(
            instrument_id=str(self.btcusdt.id),
            bar_type="BTCUSDT.BINANCE-1-MINUTE-BID-INTERNAL",
            trade_size=Decimal(0.001),
            fast_ema=10,
            slow_ema=20,
        )
        strategy = EMACross(config=config)
        self.engine.add_strategy(strategy)

        # Act
        self.engine.run()

        # Assert
        assert strategy.fast_ema.count == 10000
        assert self.engine.iteration == 40000
        btc_ending_balance = self.engine.portfolio.account(
            self.venue).balance_total(BTC)
        usdt_ending_balance = self.engine.portfolio.account(
            self.venue).balance_total(USDT)
        assert btc_ending_balance == Money(9.57200000, BTC)
        assert usdt_ending_balance == Money(10017114.27716700, USDT)
    def test_given_list_of_ticks_aggregates_tick_bars(self):
        # Arrange
        instrument = TestInstrumentProvider.default_fx_ccy("USD/JPY")
        wrangler = QuoteTickDataWrangler(instrument)
        provider = TestDataProvider()
        ticks = wrangler.process(
            provider.read_csv_ticks("truefx-usdjpy-ticks.csv"))

        bar_store = ObjectStorer()
        handler = bar_store.store
        instrument_id = TestStubs.usdjpy_id()
        bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.MID)
        bar_type = BarType(instrument_id, bar_spec)

        clock = TestClock()
        logger = Logger(clock)

        builder = BulkTickBarBuilder(instrument, bar_type, logger, handler)

        # Act
        builder.receive(ticks)

        # Assert
        assert len(bar_store.get_store()[0]) == 333
if __name__ == "__main__":
    # Configure backtest engine
    config = BacktestEngineConfig(
        trader_id="BACKTESTER-001",
    )
    # Build the backtest engine
    engine = BacktestEngine(config=config)

    # Setup trading instruments
    SIM = Venue("SIM")
    AUDUSD_SIM = TestInstrumentProvider.default_fx_ccy("AUD/USD", SIM)

    # Setup data
    provider = TestDataProvider()
    wrangler = QuoteTickDataWrangler(instrument=AUDUSD_SIM)
    ticks = wrangler.process(provider.read_csv_ticks("truefx-audusd-ticks.csv"))
    engine.add_instrument(AUDUSD_SIM)
    engine.add_ticks(ticks)

    # Create a fill model (optional)
    fill_model = FillModel(
        prob_fill_on_limit=0.2,
        prob_fill_on_stop=0.95,
        prob_slippage=0.5,
        random_seed=42,
    )

    # Optional plug in module to simulate rollover interest,
    # the data is coming from packaged test data.
    interest_rate_data = provider.read_csv("short-term-interest.csv")
Пример #19
0
    # Configure backtest engine
    config = BacktestEngineConfig(
        trader_id="BACKTESTER-001",
        use_data_cache=
        True,  # Pre-cache data for increased performance on repeated runs
    )
    # Build the backtest engine
    engine = BacktestEngine(config=config)

    # Setup trading instruments
    SIM = Venue("SIM")
    GBPUSD_SIM = TestInstrumentProvider.default_fx_ccy("GBP/USD", SIM)

    # Setup data
    provider = TestDataProvider()
    wrangler = QuoteTickDataWrangler(GBPUSD_SIM)
    ticks = wrangler.process_bar_data(
        bid_data=provider.read_csv_bars("fxcm-gbpusd-m1-bid-2012.csv"),
        ask_data=provider.read_csv_bars("fxcm-gbpusd-m1-ask-2012.csv"),
    )
    engine.add_instrument(GBPUSD_SIM)
    engine.add_ticks(ticks)

    # Create a fill model (optional)
    fill_model = FillModel(
        prob_fill_on_limit=0.2,
        prob_fill_on_stop=0.95,
        prob_slippage=0.5,
        random_seed=42,
    )