def test_can_run_multiple_strategies(self):
        # Arrange
        strategies = [
            EMACross(symbol=self.usdjpy.symbol,
                     bar_spec=TestStubs.bar_spec_1min_bid(),
                     risk_bp=10,
                     fast_ema=10,
                     slow_ema=20,
                     atr_period=20,
                     sl_atr_multiple=2.0,
                     extra_id_tag='001'),
            EMACross(symbol=self.usdjpy.symbol,
                     bar_spec=TestStubs.bar_spec_1min_bid(),
                     risk_bp=10,
                     fast_ema=10,
                     slow_ema=20,
                     atr_period=20,
                     sl_atr_multiple=2.0,
                     extra_id_tag='002')
        ]

        start = datetime(2013, 1, 2, 0, 0, 0, 0)
        stop = datetime(2013, 1, 3, 0, 0, 0, 0)

        # Act
        self.engine.run(start, stop, strategies=strategies)

        # Assert
        self.assertEqual(559, strategies[0].fast_ema.count)
        self.assertEqual(559, strategies[1].fast_ema.count)
Beispiel #2
0
    def test_run_multiple_strategies(self):
        # Arrange
        strategy1 = EMACross(
            instrument_id=self.usdjpy.id,
            bar_spec=BarSpecification(15, BarAggregation.MINUTE,
                                      PriceType.BID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
            extra_id_tag="001",
        )

        strategy2 = EMACross(
            instrument_id=self.usdjpy.id,
            bar_spec=BarSpecification(15, BarAggregation.MINUTE,
                                      PriceType.BID),
            trade_size=Decimal(1_000_000),
            fast_ema=20,
            slow_ema=40,
            extra_id_tag="002",
        )

        # Note since these strategies are operating on the same instrument_id as per
        # the EMACross BUY/SELL logic they will be flattening each others positions.
        # The purpose of the test is just to ensure multiple strategies can run together.

        # Act
        self.engine.run(strategies=[strategy1, strategy2])

        # Assert
        self.assertEqual(2689, strategy1.fast_ema.count)
        self.assertEqual(2689, strategy2.fast_ema.count)
        self.assertEqual(115043, self.engine.iteration)
        self.assertEqual(Money(994662.69, USD),
                         self.engine.portfolio.account(self.venue).balance())
Beispiel #3
0
    def test_run_for_tick_processing():
        # Arrange
        data = BacktestDataContainer()
        data.add_instrument(USDJPY_SIM)
        data.add_bars(USDJPY_SIM.symbol, BarAggregation.MINUTE, PriceType.BID, TestDataProvider.usdjpy_1min_bid())
        data.add_bars(USDJPY_SIM.symbol, BarAggregation.MINUTE, PriceType.ASK, TestDataProvider.usdjpy_1min_ask())

        strategy = EMACross(
            symbol=USDJPY_SIM.symbol,
            bar_spec=TestStubs.bar_spec_1min_bid(),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        engine = BacktestEngine(
            data=data,
            strategies=[strategy],
            bypass_logging=True,
        )

        engine.add_exchange(
            venue=Venue("SIM"),
            oms_type=OMSType.HEDGING,
            starting_balances=[Money(1_000_000, USD)],
        )

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

        stats_file = "perf_stats_tick_processing.prof"
        cProfile.runctx("engine.run(start, stop)", globals(), locals(), stats_file)
        s = pstats.Stats(stats_file)
        s.strip_dirs().sort_stats("time").print_stats()
Beispiel #4
0
    def test_run_with_ema_cross_strategy():
        # Arrange
        engine = BacktestEngine(bypass_logging=True)

        engine.add_instrument(USDJPY_SIM)
        engine.add_bars(
            USDJPY_SIM.id,
            BarAggregation.MINUTE,
            PriceType.BID,
            TestDataProvider.usdjpy_1min_bid(),
        )
        engine.add_bars(
            USDJPY_SIM.id,
            BarAggregation.MINUTE,
            PriceType.ASK,
            TestDataProvider.usdjpy_1min_ask(),
        )

        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],
        )

        strategy = EMACross(
            instrument_id=USDJPY_SIM.id,
            bar_spec=TestStubs.bar_spec_1min_bid(),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

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

        stats_file = "perf_stats_backtest_run_ema.prof"
        cProfile.runctx(
            "engine.run(start, stop, strategies=[strategy])",
            globals(),
            locals(),
            stats_file,
        )
        s = pstats.Stats(stats_file)
        s.strip_dirs().sort_stats("time").print_stats()
Beispiel #5
0
    def test_run_for_tick_processing():
        # Arrange
        engine = BacktestEngine(bypass_logging=True)

        engine.add_instrument(USDJPY_SIM)
        engine.add_bars(
            USDJPY_SIM.id,
            BarAggregation.MINUTE,
            PriceType.BID,
            TestDataProvider.usdjpy_1min_bid(),
        )
        engine.add_bars(
            USDJPY_SIM.id,
            BarAggregation.MINUTE,
            PriceType.ASK,
            TestDataProvider.usdjpy_1min_ask(),
        )

        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)],
        )

        strategy = EMACross(
            instrument_id=USDJPY_SIM.id,
            bar_spec=TestStubs.bar_spec_1min_bid(),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

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

        stats_file = "perf_stats_tick_processing.prof"
        cProfile.runctx(
            "engine.run(start, stop, strategies=[strategy])",
            globals(),
            locals(),
            stats_file,
        )
        s = pstats.Stats(stats_file)
        s.strip_dirs().sort_stats("time").print_stats()
    def test_run_ema_cross_with_minute_bar_spec(self):
        # Arrange
        strategy = EMACross(
            symbol=self.gbpusd.symbol,
            bar_spec=BarSpecification(5, BarAggregation.MINUTE, PriceType.MID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        # Act
        self.engine.run(strategies=[strategy])

        # Assert
        self.assertEqual(8353, strategy.fast_ema.count)
        self.assertEqual(120467, self.engine.iteration)
        self.assertEqual(Money(947226.84, GBP), self.engine.portfolio.account(self.venue).balance())
    def test_run_ema_cross_with_tick_bar_spec(self):
        # Arrange
        strategy = EMACross(
            symbol=self.instrument.symbol,
            bar_spec=BarSpecification(250, BarAggregation.TICK, PriceType.LAST),
            trade_size=Decimal(100),
            fast_ema=10,
            slow_ema=20,
        )

        # Act
        self.engine.run(strategies=[strategy])

        # Assert
        self.assertEqual(39, strategy.fast_ema.count)
        self.assertEqual(19998, self.engine.iteration)
        self.assertEqual(Money('995991.41500000', USDT), self.engine.portfolio.account(self.venue).balance())
    def test_run_ema_cross_strategy(self):
        # Arrange
        strategy = EMACross(
            symbol=self.usdjpy.symbol,
            bar_spec=BarSpecification(15, BarAggregation.MINUTE, PriceType.BID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        # Act
        self.engine.run(strategies=[strategy])

        # Assert - Should return expected PnL
        self.assertEqual(2689, strategy.fast_ema.count)
        self.assertEqual(115043, self.engine.iteration)
        self.assertEqual(Money(997731.21, USD), self.engine.portfolio.account(self.venue).balance())
    def test_run_ema_cross_with_tick_bar_spec(self):
        # Arrange
        strategy = EMACross(
            symbol=self.audusd.symbol,
            bar_spec=BarSpecification(100, BarAggregation.TICK, PriceType.MID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        # Act
        self.engine.run(strategies=[strategy])

        # Assert
        self.assertEqual(999, strategy.fast_ema.count)
        self.assertEqual(99999, self.engine.iteration)
        self.assertEqual(Money(995431.92, AUD), self.engine.portfolio.account(self.venue).balance())
Beispiel #10
0
    def test_run_ema_cross_with_minute_bar_spec(self):
        # Arrange
        strategy = EMACross(
            instrument_id=self.audusd.id,
            bar_spec=BarSpecification(1, BarAggregation.MINUTE, PriceType.MID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        # Act
        self.engine.run(strategies=[strategy])

        # Assert
        self.assertEqual(1771, strategy.fast_ema.count)
        self.assertEqual(99999, self.engine.iteration)
        self.assertEqual(Money(991360.19, AUD),
                         self.engine.portfolio.account(self.venue).balance())
    def test_run_ema_cross_with_tick_bar_spec(self):
        # Arrange
        strategy = EMACross(
            instrument_id=self.ethusdt.id,
            bar_spec=BarSpecification(250, BarAggregation.TICK,
                                      PriceType.LAST),
            trade_size=Decimal(100),
            fast_ema=10,
            slow_ema=20,
        )

        # Act
        self.engine.run(strategies=[strategy])

        # Assert
        self.assertEqual(279, strategy.fast_ema.count)
        self.assertEqual(69806, self.engine.iteration)
        self.assertEqual(Money("998873.43110000", USDT),
                         self.engine.portfolio.account(self.venue).balance())
Beispiel #12
0
    def test_rerunning_backtest_with_redis_db_builds_correct_index(self):
        # Arrange
        strategy = EMACross(
            instrument_id=self.usdjpy.id,
            bar_spec=BarSpecification(15, BarAggregation.MINUTE, PriceType.BID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        # Generate a lot of data
        self.engine.run(strategies=[strategy])

        # Reset engine
        self.engine.reset()
        self.engine.run()

        # Act
        # Assert
        self.assertTrue(self.engine.get_exec_engine().cache.check_integrity())
    def test_run_ema_cross_strategy(self):
        # Arrange
        strategies = [
            EMACross(symbol=self.usdjpy.symbol,
                     bar_spec=TestStubs.bar_spec_1min_bid(),
                     fast_ema=10,
                     slow_ema=20)
        ]

        start = datetime(2013, 1, 2, 0, 0, 0, 0)
        stop = datetime(2013, 1, 3, 0, 0, 0, 0)

        # Act
        self.engine.run(start, stop, strategies=strategies)

        # Assert
        self.assertEqual(559, strategies[0].fast_ema.count)
        self.assertEqual(-1857.67,
                         self.engine.analyzer.get_performance_stats()
                         ['PNL'])  # Money represented as double here
    def test_rerun_ema_cross_strategy_returns_identical_performance(self):
        # Arrange
        strategy = EMACross(
            symbol=self.usdjpy.symbol,
            bar_spec=BarSpecification(15, BarAggregation.MINUTE, PriceType.BID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        self.engine.run(strategies=[strategy])
        result1 = self.engine.analyzer.get_performance_stats_pnls()

        # Act
        self.engine.reset()
        self.engine.run()
        result2 = self.engine.analyzer.get_performance_stats_pnls()

        # Assert
        self.assertEqual(all(result1), all(result2))
    def test_exec_cache_check_integrity_when_index_cleared_fails(self):
        # Arrange
        strategy = EMACross(
            symbol=self.usdjpy.symbol,
            bar_spec=BarSpecification(15, BarAggregation.MINUTE,
                                      PriceType.BID),
            trade_size=Decimal(1_000_000),
            fast_ema=10,
            slow_ema=20,
        )

        # Generate a lot of data
        self.engine.run(strategies=[strategy])

        # Clear index
        self.cache.clear_index()

        # Act
        # Assert
        self.assertFalse(self.cache.check_integrity())
    def test_rerun_ema_cross_strategy_returns_identical_performance(self):
        # Arrange
        strategies = [
            EMACross(symbol=self.usdjpy.symbol,
                     bar_spec=TestStubs.bar_spec_1min_bid(),
                     fast_ema=10,
                     slow_ema=20)
        ]

        start = datetime(2013, 1, 2, 0, 0, 0, 0)
        stop = datetime(2013, 1, 3, 0, 0, 0, 0)

        self.engine.run(start, stop, strategies=strategies)
        result1 = self.engine.analyzer.get_performance_stats()

        # Act
        self.engine.run(start, stop)
        result2 = self.engine.analyzer.get_performance_stats()

        # Assert
        self.assertEqual(all(result1), all(result2))
Beispiel #17
0
    def test_run_for_tick_processing(self):
        # Arrange
        usdjpy = InstrumentLoader.default_fx_ccy(TestStubs.symbol_usdjpy_fxcm())

        data = BacktestDataContainer()
        data.add_instrument(usdjpy)
        data.add_bars(usdjpy.symbol, BarAggregation.MINUTE, PriceType.BID, TestDataProvider.usdjpy_1min_bid())
        data.add_bars(usdjpy.symbol, BarAggregation.MINUTE, PriceType.ASK, TestDataProvider.usdjpy_1min_ask())

        strategies = [EMACross(
            symbol=usdjpy.symbol,
            bar_spec=TestStubs.bar_spec_1min_bid(),
            fast_ema=10,
            slow_ema=20)]

        config = BacktestConfig(
            exec_db_type="in-memory",
            bypass_logging=True,
            console_prints=False)

        engine = BacktestEngine(
            data=data,
            strategies=strategies,
            venue=Venue("FXCM"),
            oms_type=OMSType.HEDGING,
            generate_position_ids=True,
            config=config,
            fill_model=None,
        )

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

        stats_file = "perf_stats_tick_processing.prof"
        cProfile.runctx("engine.run(start, stop)", globals(), locals(), stats_file)
        s = pstats.Stats(stats_file)
        s.strip_dirs().sort_stats("time").print_stats()

        self.assertTrue(True)
Beispiel #18
0
    def test_run_for_tick_processing(self):
        # Arrange
        usdjpy = TestStubs.instrument_usdjpy()

        data = BacktestDataContainer()
        data.add_instrument(usdjpy)
        data.add_bars(usdjpy.symbol, BarStructure.MINUTE, PriceType.BID, TestDataProvider.usdjpy_1min_bid())
        data.add_bars(usdjpy.symbol, BarStructure.MINUTE, PriceType.ASK, TestDataProvider.usdjpy_1min_ask())

        strategies = [EMACross(
            symbol=usdjpy.symbol,
            bar_spec=TestStubs.bar_spec_1min_bid(),
            risk_bp=10,
            fast_ema=10,
            slow_ema=20,
            atr_period=20,
            sl_atr_multiple=2.0)]

        config = BacktestConfig(
            exec_db_type='in-memory',
            bypass_logging=True,
            console_prints=False)

        engine = BacktestEngine(
            data=data,
            strategies=strategies,
            config=config,
            fill_model=None)

        start = datetime(2013, 2, 1, 0, 0, 0, 0, tzinfo=timezone.utc)
        stop = datetime(2013, 2, 10, 0, 0, 0, 0, tzinfo=timezone.utc)

        stats_file = 'perf_stats_tick_processing.prof'
        cProfile.runctx('engine.run(start, stop)', globals(), locals(), stats_file)
        s = pstats.Stats(stats_file)
        s.strip_dirs().sort_stats("time").print_stats()

        self.assertTrue(True)
Beispiel #19
0
# BAR_SPEC_FX = BarSpecification(100, BarStructure.TICK, PriceType.BID)
# BAR_SPEC_CFD = BarSpecification(500, BarStructure.TICK, PriceType.BID)

symbols_fx = [
    Symbol('AUD/USD', Venue('FXCM')),
    Symbol('EUR/USD', Venue('FXCM')),
    Symbol('GBP/USD', Venue('FXCM')),
    Symbol('USD/JPY', Venue('FXCM')),
]

strategies_fx = []
for symbol in symbols_fx:
    strategies_fx.append(
        EMACross(symbol,
                 BAR_SPEC_FX,
                 risk_bp=10.0,
                 fast_ema=10,
                 slow_ema=20,
                 atr_period=20))

# symbols_cfd = [
#     Symbol('XAUUSD', Venue('FXCM')),
#     Symbol('SPX500', Venue('FXCM')),
#     Symbol('AUS200', Venue('FXCM')),
#     Symbol('USOil', Venue('FXCM')),
#     Symbol('GER30', Venue('FXCM')),
# ]

# strategies_cfd = []
# for symbol in symbols_cfd:
#     strategies_fx.append(EMACrossPy(
#         symbol,