Example #1
0
def test_descriptive_stats():
    check_values = []

    scheduler = HistoricNetworkScheduler(0, 1000)
    network = scheduler.get_network()
    values = From(scheduler, [0.0, 3.2, 2.1, 2.9, 8.3, 5.7])

    max_value = Max(network, values)
    min_value = Min(network, values)
    avg = Mean(network, values)
    stddev = Stddev(network, values)

    check_values.extend([max_value, min_value, avg, stddev])

    # noinspection PyUnusedLocal
    def print_stats(params):
        print(f"min = {min_value.get_value()}; max = {max_value.get_value()}; "
              f"avg = {avg.get_value():.2f}; stddev = {stddev.get_value():.2f}")

    Lambda(network, [min_value, max_value, avg, stddev], print_stats)

    scheduler.run()
    assert check_values[0].get_value() == 8.3
    assert check_values[1].get_value() == 0.0
    assert math.isclose(check_values[2].get_value(), 3.7, abs_tol=0.00001)
    assert math.isclose(check_values[3].get_value(), 3.24507, abs_tol=0.00001)
Example #2
0
def test_filter():
    scheduler = HistoricNetworkScheduler(0, 30 * 1000)
    network = scheduler.get_network()
    values = From(scheduler, [0.0, -3.2, 2.1, -2.9, 8.3, -5.7])
    filt = Filter(network, values, lambda x: x >= 0.0)
    Do(network, filt, lambda: print(f'{filt.get_value()}'))
    scheduler.run()
    assert filt.get_value() == 8.3
Example #3
0
def test_map_reduce():
    scheduler = HistoricNetworkScheduler(0, 30 * 1000)
    network = scheduler.get_network()
    values = From(scheduler, [0.0, 3.2, 2.1, 2.9, 8.3, 5.7])
    mapper = Map(network, values, lambda x: round(x))
    accumulator = Scan(network, mapper)
    Do(network, accumulator, lambda: print(f'{accumulator.get_value()}'))
    scheduler.run()
    assert accumulator.get_value() == 22.0
Example #4
0
    def __init__(self, config: BacktestConfig):
        logger = logging.getLogger(__name__)
        logger.info('Serenity backtester starting up')

        sys.path.append(str(config.get_strategy_basedir()))

        bt_env = config.get_env()

        exchange_id = bt_env.getenv('EXCHANGE_ID', 'autofill')
        instance_id = bt_env.getenv('EXCHANGE_INSTANCE', 'prod')
        account = bt_env.getenv('EXCHANGE_ACCOUNT', 'Main')

        self.logger.info('Connecting to Serenity database')
        conn = connect_serenity_db()
        conn.autocommit = True
        cur = conn.cursor()

        self.scheduler = HistoricNetworkScheduler(
            config.get_start_time_millis(), config.get_end_time_millis())
        instrument_cache = InstrumentCache(cur, TypeCodeCache(cur))

        oms = OrderManagerService(self.scheduler)

        md_service = AzureHistoricMarketdataService(
            self.scheduler, bt_env.getenv('AZURE_CONNECT_STR'))
        mark_service = MarketdataMarkService(self.scheduler.get_network(),
                                             md_service)
        op_service = OrderPlacerService(self.scheduler, oms)
        op_service.register_order_placer(
            f'{exchange_id}:{instance_id}',
            AutoFillOrderPlacer(self.scheduler, oms, md_service, account))

        xps = NullExchangePositionService(self.scheduler)

        extra_outputs_txt = bt_env.getenv('EXTRA_OUTPUTS')
        if extra_outputs_txt is None:
            extra_outputs = []
        else:
            extra_outputs = extra_outputs_txt.split(',')
        self.dcs = HDF5DataCaptureService(Mode.BACKTEST, self.scheduler,
                                          extra_outputs)

        # wire up orders and fills from OMS
        Do(self.scheduler.get_network(), oms.get_orders(),
           lambda: self.dcs.capture_order(oms.get_orders().get_value()))
        Do(self.scheduler.get_network(), oms.get_order_events(),
           lambda: self.dcs.capture_fill(oms.get_order_events().get_value()))

        self.strategy_name = config.get_strategy_name()
        strategy_env = config.get_strategy_env()
        ctx = StrategyContext(self.scheduler, instrument_cache, md_service,
                              mark_service, op_service,
                              PositionService(self.scheduler, oms), xps,
                              self.dcs, strategy_env.values)
        strategy_instance = config.get_strategy_instance()
        strategy_instance.init(ctx)
        strategy_instance.start()
Example #5
0
def test_running_sum():
    check_values = []

    scheduler = HistoricNetworkScheduler(0, 1000)
    network = scheduler.get_network()
    values = From(scheduler, [0.0, 3.2, 2.1, 2.9, 8.3, 5.7])
    total = RunningSum(network, values)
    check_values.append(total)
    Lambda(network, total, lambda x: print(f'{x[0].get_value():.2f}'))

    scheduler.run()
    assert check_values[0].get_value() == 22.2
Example #6
0
    def __init__(self, scheduler: HistoricNetworkScheduler,
                 azure_connect_str: str):
        self.scheduler = scheduler
        self.azure_connect_str = azure_connect_str
        self.subscribed_instruments = MutableSignal()
        self.scheduler.get_network().attach(self.subscribed_instruments)

        self.start_time = scheduler.get_clock().get_start_time()
        self.end_time = scheduler.get_clock().get_end_time()

        self.all_subscribed = set()
        self.book_signal_by_symbol = {}
        self.trade_signal_by_symbol = {}
Example #7
0
    def __init__(self, scheduler: HistoricNetworkScheduler):
        self.scheduler = scheduler
        self.subscribed_instruments = MutableSignal()
        self.scheduler.get_network().attach(self.subscribed_instruments)

        self.start_time = scheduler.get_clock().get_start_time()
        self.end_time = scheduler.get_clock().get_end_time()

        self.all_subscribed = set()
        self.book_signal_by_symbol = {}
        self.trade_signal_by_symbol = {}

        self.credential = DeviceCodeCredential(client_id=get_global_defaults()['azure']['client_id'],
                                               tenant_id=get_global_defaults()['azure']['tenant_id'])
Example #8
0
def test_oms_cancel_not_pending(mocker: MockFixture):
    scheduler = HistoricNetworkScheduler(0, 1000)
    oms = OrderManagerService(scheduler)
    order_events = []
    Do(scheduler.get_network(), oms.get_order_events(),
       lambda: order_events.append(oms.get_order_events().get_value()))
    instrument = mocker.MagicMock(ExchangeInstrument)
    order = MarketOrder(10, instrument, Side.BUY, 'Main')
    order.set_order_id(str(uuid1()))
    oms.pending_new(order)
    oms.new(order, str(uuid1()))
    oms.apply_cancel(order, str(uuid1()))
    scheduler.run()
    assert (isinstance(order_events[2], CancelReject))
    assert (order_events[2].get_message() ==
            'Attempt to apply cancel when not pending')
Example #9
0
def test_oms_late_fill(mocker: MockFixture):
    scheduler = HistoricNetworkScheduler(0, 1000)
    oms = OrderManagerService(scheduler)
    order_events = []
    Do(scheduler.get_network(), oms.get_order_events(),
       lambda: order_events.append(oms.get_order_events().get_value()))
    instrument = mocker.MagicMock(ExchangeInstrument)
    order = MarketOrder(10, instrument, Side.BUY, 'Main')
    order.set_order_id(str(uuid1()))
    oms.pending_new(order)
    oms.new(order, str(uuid1()))
    oms.pending_cancel(order)
    oms.apply_cancel(order, str(uuid1()))
    oms.apply_fill(order, 1, 10_000, str(uuid1()))
    scheduler.run()
    assert (isinstance(order_events[4], Reject))
    assert (order_events[4].get_message() == 'Order canceled')
Example #10
0
def test_oms_regular_sequence(mocker: MockFixture):
    scheduler = HistoricNetworkScheduler(0, 1000)
    oms = OrderManagerService(scheduler)
    order_statuses = []
    Do(
        scheduler.get_network(), oms.get_order_events(), lambda: order_statuses
        .append(oms.get_order_events().get_value().get_order_status()))
    instrument = mocker.MagicMock(ExchangeInstrument)
    order = MarketOrder(10, instrument, Side.BUY, 'Main')
    order.set_order_id(str(uuid1()))
    oms.pending_new(order)
    oms.new(order, str(uuid1()))
    oms.apply_fill(order, 1, 10_000, str(uuid1()))
    oms.pending_cancel(order)
    oms.apply_cancel(order, str(uuid1()))
    scheduler.run()
    assert (order_statuses == [
        OrderStatus.PENDING_NEW, OrderStatus.NEW, OrderStatus.PARTIALLY_FILLED,
        OrderStatus.PENDING_CANCEL, OrderStatus.CANCELED
    ])
Example #11
0
def test_routing_marketdata_service(mocker: MockFixture):
    scheduler = HistoricNetworkScheduler(0, 1000)
    mds1 = mocker.MagicMock(MarketdataService)
    mds2 = mocker.MagicMock(MarketdataService)
    rules = CompositeRoutingRule([
        ExchangeRoutingRule('POLYGON', mds1),
        ExchangeRoutingRule('PHEMEX', mds2)
    ])
    router = RoutingMarketdataService(scheduler.get_network(), rules)

    # noinspection DuplicatedCode
    venue_type = VenueType(-1, 'DataAggregator')
    exch1 = Exchange(-1, venue_type, 'POLYGON', 'Polygon.io')
    instr_type1 = InstrumentType(-1, 'ETF')
    instr1 = Instrument(-1, instr_type1, 'SPY')
    xinstr1 = ExchangeInstrument(-1, exch1, instr1, 'SPY')

    venue_type = VenueType(-1, 'CryptoExchange')
    exch2 = Exchange(-1, venue_type, 'PHEMEX', 'Phemex')
    instr_type2 = InstrumentType(-1, 'CurrencyPair')
    instr2 = Instrument(-1, instr_type2, 'BTCUSD')
    xinstr2 = ExchangeInstrument(-1, exch2, instr2, 'BTCUSD')

    assert router.get_subscribed_instruments() is not None

    assert router.get_order_book_events(
        xinstr1) is mds1.get_order_book_events()
    assert router.get_order_book_events(
        xinstr2) is mds2.get_order_book_events()

    assert router.get_order_books(xinstr1) is mds1.get_order_books()
    assert router.get_order_books(xinstr2) is mds2.get_order_books()

    assert router.get_trades(xinstr1) is mds1.get_trades()
    assert router.get_trades(xinstr2) is mds2.get_trades()

    scheduler.run()
Example #12
0
def test_repeating_timer():
    # run for one minute
    scheduler = HistoricNetworkScheduler(0, 60 * 1000)

    tz = pytz.timezone('US/Eastern')
    timer = RepeatingTimer(scheduler, datetime.timedelta(seconds=15))
    timestamps = list()
    Do(scheduler.get_network(), timer,
       lambda: timestamps.append(scheduler.get_clock().get_time(tz)))
    scheduler.run()
    assert len(timestamps) == 4
    assert str(timestamps[3]) == '1969-12-31 19:01:00-05:00'
Example #13
0
def test_alarm():
    # run for one day
    scheduler = HistoricNetworkScheduler(0, 60 * 60 * 24 * 1000)

    # schedule at 4pm US/Eastern
    tz = pytz.timezone('US/Eastern')
    alarm = Alarm(scheduler, datetime.time(16, 00, 00), tz)
    timestamps = list()
    Do(scheduler.get_network(), alarm,
       lambda: timestamps.append(scheduler.get_clock().get_time(tz)))
    scheduler.run()
    assert len(timestamps) == 1
Example #14
0
def main(config_path: str, strategy_dir: str, start_time: str, end_time: str):
    init_logging()

    config = toml.load(config_path)
    strategy_module = config['strategy']['module']
    strategy_class = config['strategy']['class']
    loader = StrategyLoader(Path(strategy_dir))
    strategy_instance = loader.load(strategy_module, strategy_class)

    scheduler = HistoricNetworkScheduler.new_instance(start_time, end_time)
    backtester = InvestmentStrategyBacktester(scheduler)
    portfolio = backtester.run(strategy_instance, config)
    scheduler.run()

    for account in portfolio.get_accounts():
        print(f'Account: [{account.get_name()}]')
        print(f'\tcash: {account.get_cash_balance().get_balance()}')
        for position in account.get_positions():
            print(
                f'\t{position.get_tradable().get_symbol()}: {position.get_qty()} shares ({position.get_notional()})'
            )
Example #15
0
def test_hello_world():
    scheduler = HistoricNetworkScheduler(0, 30 * 1000)
    signal = From(scheduler, ['world'])
    Do(scheduler.get_network(), signal,
       lambda: print(f'Hello, {signal.get_value()}!'))
    scheduler.run()
Example #16
0
def test_buffer_with_time_historic():
    scheduler = HistoricNetworkScheduler(0, 30 * 1000)
    network = scheduler.get_network()
    values = MutableSignal()
    scheduler.schedule_update_at(values, 1.0, 1000)
    scheduler.schedule_update_at(values, -3.2, 2000)
    scheduler.schedule_update_at(values, 2.1, 10000)
    scheduler.schedule_update_at(values, -2.9, 15000)
    scheduler.schedule_update_at(values, 8.3, 25000)
    scheduler.schedule_update_at(values, -5.7, 30000)

    buffer = BufferWithTime(scheduler, values, timedelta(seconds=5))
    Do(network, buffer, lambda: print(f'{buffer.get_value()}'))
    scheduler.run()