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())
async def run_test(): # Arrange with open(TEST_PATH + "fetch_ohlcv.json") as response: fetch_ohlcv = json.load(response) self.mock_ccxt.fetch_ohlcv = fetch_ohlcv self.data_engine.start() # Also starts client await asyncio.sleep(0.3) # Allow engine message queue to start handler = ObjectStorer() bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST) bar_type = BarType(symbol=ETHUSDT, bar_spec=bar_spec) request = DataRequest( venue=BINANCE, data_type=Bar, metadata={ "BarType": bar_type, "FromDateTime": None, "ToDateTime": None, "Limit": 100, }, callback=handler.store_2, request_id=self.uuid_factory.generate(), request_timestamp=self.clock.utc_now(), ) # Act self.data_engine.send(request) await asyncio.sleep(0.3) # Assert self.assertEqual(1, self.data_engine.response_count) self.assertEqual(1, handler.count) self.assertEqual(100, len(handler.get_store()[0][1])) # Tear Down self.data_engine.stop() await self.data_engine.get_run_queue_task()
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())
def test_run_ema_cross_strategy(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, ) # 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.23, USD), self.engine.portfolio.account(self.venue).balance())
def test_update_sends_bar_to_handler(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store_2 symbol = TestStubs.symbol_audusd_fxcm() bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.MID) bar_type = BarType(symbol, bar_spec) aggregator = TickBarAggregator(bar_type, handler, TestLogger(TestClock())) tick1 = QuoteTick(symbol=AUDUSD_FXCM, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH) tick2 = QuoteTick(symbol=AUDUSD_FXCM, bid=Price("1.00002"), ask=Price("1.00005"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH) tick3 = QuoteTick(symbol=AUDUSD_FXCM, bid=Price("1.00000"), ask=Price("1.00003"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH) # Act aggregator.handle_quote_tick(tick1) aggregator.handle_quote_tick(tick2) aggregator.handle_quote_tick(tick3) # Assert self.assertEqual(1, len(bar_store.get_store())) self.assertEqual(Price("1.000025"), bar_store.get_store()[0][1].open) self.assertEqual(Price("1.000035"), bar_store.get_store()[0][1].high) self.assertEqual(Price("1.000015"), bar_store.get_store()[0][1].low) self.assertEqual(Price('1.000015'), bar_store.get_store()[0][1].close) self.assertEqual(Quantity(6), bar_store.get_store()[0][1].volume)
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_run_ema_cross_with_minute_bar_spec(self): # Arrange strategy = EMACross( instrument_id=self.gbpusd.id, 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_total(GBP), )
def test_instantiate_given_invalid_bar_spec_raises_value_error(self): # Arrange clock = TestClock() bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(100, BarAggregation.TICK, PriceType.MID) bar_type = BarType(instrument_id, bar_spec) # Act # Assert self.assertRaises( ValueError, TimeBarAggregator, bar_type, handler, True, clock, TestLogger(clock), )
def test_run_ema_cross_with_tick_bar_spec(self): # Arrange strategy = EMACross( instrument_id=self.audusd.id, 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_total(AUD), )
def test_instantiate_given_invalid_bar_spec_raises_value_error(self): # Arrange clock = TestClock() bar_store = ObjectStorer() handler = bar_store.store instrument = AUDUSD_SIM bar_spec = BarSpecification(100, BarAggregation.TICK, PriceType.MID) bar_type = BarType(instrument.id, bar_spec) # Act # Assert with pytest.raises(ValueError): TimeBarAggregator( instrument, bar_type, handler, True, clock, Logger(clock), )
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_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_str_repr(self): # Arrange instrument_id = InstrumentId(Symbol("GBP/USD"), Venue("SIM")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) bar = Bar( Price("1.00001"), Price("1.00004"), Price("1.00002"), Price("1.00003"), Quantity(100000), UNIX_EPOCH, ) bar_data = BarData(bar_type, bar) # Act # Assert assert "BarData(bar_type=GBP/USD.SIM-1-MINUTE-BID, bar=1.00001,1.00004,1.00002,1.00003,100000,1970-01-01T00:00:00.000Z)" == str( bar_data) # noqa assert "BarData(bar_type=GBP/USD.SIM-1-MINUTE-BID, bar=1.00001,1.00004,1.00002,1.00003,100000,1970-01-01T00:00:00.000Z)" == repr( bar_data) # noqa
def test_subscribe_bar_type_then_subscribes(self): # Arrange self.data_engine.register_client(self.binance_client) self.binance_client.connect() bar_spec = BarSpecification(1000, BarAggregation.TICK, PriceType.MID) bar_type = BarType(ETHUSDT_BINANCE.id, bar_spec, internal_aggregation=True) handler = ObjectStorer() subscribe = Subscribe( provider=BINANCE.value, data_type=DataType(Bar, metadata={"BarType": bar_type}), handler=handler.store_2, command_id=self.uuid_factory.generate(), command_timestamp=self.clock.utc_now(), ) # Act self.data_engine.execute(subscribe) # Assert self.assertEqual([bar_type], self.data_engine.subscribed_bars)
def test_process_bar_when_subscriber_then_sends_to_registered_handler( self): # Arrange self.data_engine.register_client(self.binance_client) self.binance_client.connect() bar_spec = BarSpecification(1000, BarAggregation.TICK, PriceType.MID) bar_type = BarType(ETHUSDT_BINANCE.symbol, bar_spec, is_internal_aggregation=True) handler = ObjectStorer() subscribe = Subscribe( venue=BINANCE, data_type=Bar, metadata={"BarType": bar_type}, handler=handler.store_2, command_id=self.uuid_factory.generate(), command_timestamp=self.clock.utc_now(), ) self.data_engine.execute(subscribe) bar = Bar( Price("1051.00000"), Price("1055.00000"), Price("1050.00000"), Price("1052.00000"), Quantity(100), UNIX_EPOCH, ) data = BarData(bar_type, bar) # Act self.data_engine.process(data) # Assert self.assertEqual([(bar_type, bar)], handler.get_store())
def test_process_bar_when_subscriber_then_sends_to_registered_handler( self): # Arrange self.data_engine.register_client(self.binance_client) self.binance_client.connect() bar_spec = BarSpecification(1000, BarAggregation.TICK, PriceType.MID) bar_type = BarType(ETHUSDT_BINANCE.id, bar_spec, internal_aggregation=True) handler = ObjectStorer() subscribe = Subscribe( client_id=ClientId(BINANCE.value), data_type=DataType(Bar, metadata={"bar_type": bar_type}), handler=handler.store, command_id=self.uuid_factory.generate(), timestamp_ns=self.clock.timestamp_ns(), ) self.data_engine.execute(subscribe) bar = Bar( bar_type, Price.from_str("1051.00000"), Price.from_str("1055.00000"), Price.from_str("1050.00000"), Price.from_str("1052.00000"), Quantity.from_int(100), 0, 0, ) # Act self.data_engine.process(bar) # Assert self.assertEqual([bar], handler.get_store())
def test_handle_quote_tick_when_count_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store symbol = TestStubs.symbol_audusd_fxcm() bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.MID) bar_type = BarType(symbol, bar_spec) aggregator = TickBarAggregator(bar_type, handler, TestLogger(TestClock())) tick1 = QuoteTick( symbol=AUDUSD_SIM.symbol, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(1), ask_size=Quantity(1), timestamp=UNIX_EPOCH, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
def test_handle_trade_tick_when_volume_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.LAST) bar_type = BarType(instrument_id, bar_spec) aggregator = VolumeBarAggregator(bar_type, handler, Logger(TestClock())) tick1 = TradeTick( instrument_id=AUDUSD_SIM.id, price=Price("1.00001"), size=Quantity(1), side=OrderSide.BUY, match_id=TradeMatchId("123456"), timestamp_ns=0, ) # Act aggregator.handle_trade_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
def test_handle_quote_tick_when_volume_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(10000, BarAggregation.VOLUME, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) aggregator = VolumeBarAggregator(bar_type, handler, Logger(TestClock())) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price("1.00001"), ask=Price("1.00004"), bid_size=Quantity(3000), ask_size=Quantity(2000), timestamp_ns=0, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
def test_handle_trade_tick_when_count_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store symbol = TestStubs.symbol_audusd_fxcm() bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.LAST) bar_type = BarType(symbol, bar_spec) aggregator = TickBarAggregator(bar_type, handler, TestLogger(TestClock())) tick1 = TradeTick( symbol=AUDUSD_SIM.symbol, price=Price("1.00001"), size=Quantity(1), side=OrderSide.BUY, match_id=TradeMatchId("123456"), timestamp=UNIX_EPOCH, ) # Act aggregator.handle_trade_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
def test_str_repr(self): # Arrange symbol = Symbol("GBP/USD", Venue("SIM")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type = BarType(symbol, bar_spec) bar = Bar( Price("1.00001"), Price("1.00004"), Price("1.00002"), Price("1.00003"), Quantity(100000), UNIX_EPOCH, ) bar_data = BarData(bar_type, bar) # Act # Assert self.assertEqual( "BarData(bar_type=GBP/USD.SIM-1-MINUTE-BID, bar=1.00001,1.00004,1.00002,1.00003,100000,1970-01-01T00:00:00.000Z)", str(bar_data)) # noqa self.assertEqual( "BarData(bar_type=GBP/USD.SIM-1-MINUTE-BID, bar=1.00001,1.00004,1.00002,1.00003,100000,1970-01-01T00:00:00.000Z)", repr(bar_data)) # noqa
def test_handle_quote_tick_when_count_below_threshold_updates(self): # Arrange bar_store = ObjectStorer() handler = bar_store.store instrument_id = TestStubs.audusd_id() bar_spec = BarSpecification(3, BarAggregation.TICK, PriceType.MID) bar_type = BarType(instrument_id, bar_spec) aggregator = TickBarAggregator(bar_type, handler, Logger(TestClock())) tick1 = QuoteTick( instrument_id=AUDUSD_SIM.id, bid=Price.from_str("1.00001"), ask=Price.from_str("1.00004"), bid_size=Quantity.from_int(1), ask_size=Quantity.from_int(1), timestamp_origin_ns=0, timestamp_ns=0, ) # Act aggregator.handle_quote_tick(tick1) # Assert self.assertEqual(0, len(bar_store.get_store()))
class TestBarSpecification: def test_bar_spec_equality(self): # Arrange bar_spec1 = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_spec2 = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_spec3 = BarSpecification(1, BarAggregation.MINUTE, PriceType.ASK) # Act # Assert assert bar_spec1 == bar_spec1 assert bar_spec1 == bar_spec2 assert bar_spec1 != bar_spec3 def test_bar_spec_hash_str_and_repr(self): # Arrange bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) # Act # Assert assert isinstance(hash(bar_spec), int) assert str(bar_spec) == "1-MINUTE-BID" assert repr(bar_spec) == "BarSpecification(1-MINUTE-BID)" @pytest.mark.parametrize( "value", ["", "1", "-1-TICK-MID", "1-TICK_MID"], ) def test_from_str_given_various_invalid_strings_raises_value_error( self, value): # Arrange # Act # Assert with pytest.raises(ValueError): BarSpecification.from_str(value) @pytest.mark.parametrize( "value, expected", [ [ "1-MINUTE-BID", BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) ], [ "15-MINUTE-MID", BarSpecification(15, BarAggregation.MINUTE, PriceType.MID), ], [ "100-TICK-LAST", BarSpecification(100, BarAggregation.TICK, PriceType.LAST), ], [ "10000-VALUE_IMBALANCE-MID", BarSpecification(10000, BarAggregation.VALUE_IMBALANCE, PriceType.MID), ], ], ) def test_from_str_given_various_valid_string_returns_expected_specification( self, value, expected): # Arrange # Act spec = BarSpecification.from_str(value) # Assert assert spec == expected @pytest.mark.parametrize( "bar_spec, is_time_aggregated, is_threshold_aggregated, is_information_aggregated", [ [ BarSpecification(1, BarAggregation.SECOND, PriceType.BID), True, False, False, ], [ BarSpecification(1, BarAggregation.MINUTE, PriceType.BID), True, False, False, ], [ BarSpecification(1000, BarAggregation.TICK, PriceType.MID), False, True, False, ], [ BarSpecification(10000, BarAggregation.VALUE_RUNS, PriceType.MID), False, False, True, ], ], ) def test_aggregation_queries( self, bar_spec, is_time_aggregated, is_threshold_aggregated, is_information_aggregated, ): # Arrange # Act # Assert assert is_time_aggregated == bar_spec.is_time_aggregated() assert is_threshold_aggregated == bar_spec.is_threshold_aggregated() assert is_information_aggregated == bar_spec.is_information_aggregated( )
class TestBarType: def test_bar_type_equality(self): # Arrange instrument_id1 = InstrumentId(Symbol("AUD/USD"), Venue("SIM")) instrument_id2 = InstrumentId(Symbol("GBP/USD"), Venue("SIM")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type1 = BarType(instrument_id1, bar_spec) bar_type2 = BarType(instrument_id1, bar_spec) bar_type3 = BarType(instrument_id2, bar_spec) # Act # Assert assert bar_type1 == bar_type1 assert bar_type1 == bar_type2 assert bar_type1 != bar_type3 def test_bar_type_to_serializable_string(self): # Arrange instrument_id = InstrumentId(Symbol("AUD/USD"), Venue("IDEALPRO")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) # Act result = bar_type.to_serializable_str() # Assert assert "AUD/USD.IDEALPRO-1-MINUTE-BID" == result def test_bar_type_hash_str_and_repr(self): # Arrange instrument_id = InstrumentId(Symbol("AUD/USD"), Venue("SIM")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type = BarType(instrument_id, bar_spec) # Act # Assert assert isinstance(hash(bar_type), int) assert str(bar_type) == "AUD/USD.SIM-1-MINUTE-BID" assert (repr(bar_type) == "BarType(AUD/USD.SIM-1-MINUTE-BID, internal_aggregation=True)") @pytest.mark.parametrize( "value", ["", "AUD/USD", "AUD/USD.IDEALPRO-1-MILLISECOND-BID"], ) def test_from_str_given_various_invalid_strings_raises_value_error( self, value): # Arrange # Act # Assert with pytest.raises(ValueError): BarType.from_serializable_str(value) @pytest.mark.parametrize( "value, expected", [ [ "AUD/USD.IDEALPRO-1-MINUTE-BID", BarType( InstrumentId(Symbol("AUD/USD"), Venue("IDEALPRO")), BarSpecification(1, BarAggregation.MINUTE, PriceType.BID), ), ], # noqa [ "GBP/USD.SIM-1000-TICK-MID", BarType( InstrumentId(Symbol("GBP/USD"), Venue("SIM")), BarSpecification(1000, BarAggregation.TICK, PriceType.MID), ), ], # noqa [ "AAPL.NYSE-1-HOUR-MID", BarType( InstrumentId(Symbol("AAPL"), Venue("NYSE")), BarSpecification(1, BarAggregation.HOUR, PriceType.MID), ), ], # noqa [ "BTC/USDT.BINANCE-100-TICK-LAST", BarType( InstrumentId(Symbol("BTC/USDT"), Venue("BINANCE")), BarSpecification(100, BarAggregation.TICK, PriceType.LAST), ), ], ], # noqa ) def test_from_str_given_various_valid_string_returns_expected_specification( self, value, expected): # Arrange # Act bar_type = BarType.from_serializable_str(value, internal_aggregation=True) # Assert assert expected == bar_type
from nautilus_trader.model.bar import Bar from nautilus_trader.model.bar import BarSpecification from nautilus_trader.model.bar import BarType from nautilus_trader.model.enums import BarAggregation from nautilus_trader.model.enums import PriceType from nautilus_trader.model.identifiers import InstrumentId from nautilus_trader.model.identifiers import Symbol from nautilus_trader.model.identifiers import Venue from nautilus_trader.model.objects import Price from nautilus_trader.model.objects import Quantity from tests.test_kit.stubs import TestStubs AUDUSD_SIM = TestStubs.audusd_id() GBPUSD_SIM = TestStubs.gbpusd_id() ONE_MIN_BID = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) AUDUSD_1_MIN_BID = BarType(AUDUSD_SIM, ONE_MIN_BID) GBPUSD_1_MIN_BID = BarType(GBPUSD_SIM, ONE_MIN_BID) class TestBarSpecification: def test_bar_spec_equality(self): # Arrange bar_spec1 = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_spec2 = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_spec3 = BarSpecification(1, BarAggregation.MINUTE, PriceType.ASK) # Act # Assert assert bar_spec1 == bar_spec1 assert bar_spec1 == bar_spec2
"BINANCE_ACCOUNT_ID", # value is the environment variable key "api_key": "BINANCE_API_KEY", # value is the environment variable key "api_secret": "BINANCE_API_SECRET", # value is the environment variable key "sandbox_mode": False, # If clients use the testnet }, }, } # Instantiate your strategies to pass into the trading node. You could add # custom options into the configuration file or even use another configuration # file. strategy = EMACross( symbol=Symbol("ETH/USDT", Venue("BINANCE")), bar_spec=BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST), fast_ema_period=10, slow_ema_period=20, trade_size=Decimal("0.05"), order_id_tag="001", ) # Instantiate the node passing a list of strategies and configuration node = TradingNode(strategies=[strategy], config=config) # Stop and dispose of the node with SIGINT/CTRL+C if __name__ == "__main__": try: node.start() finally: node.dispose()
def bar_spec_1min_mid() -> BarSpecification: return BarSpecification(1, BarAggregation.MINUTE, PriceType.MID)
def bar_spec_100tick_last() -> BarSpecification: return BarSpecification(100, BarAggregation.TICK, PriceType.LAST)
def bar_spec_1sec_mid() -> BarSpecification: return BarSpecification(1, BarAggregation.SECOND, PriceType.MID)
"BINANCE_ACCOUNT_ID", # value is the environment variable key "api_key": "BINANCE_API_KEY", # value is the environment variable key "api_secret": "BINANCE_API_SECRET", # value is the environment variable key "sandbox_mode": False, # If clients use the testnet }, }, } # BarSpecification options # ------------------------ # price types include BID, ASK, MID, LAST # Current aggregations TICK, SECOND, MINUTE, HOUR, DAY, VOLUME, VALUE # These can be combined in any way, for example; tick_bars = BarSpecification(100, BarAggregation.TICK, PriceType.LAST) time_bars = BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST) volu_bars = BarSpecification(100, BarAggregation.VOLUME, PriceType.MID) valu_bars = BarSpecification(1_000_000, BarAggregation.VALUE, PriceType.MID) # Instantiate your strategies to pass into the trading node. You could add # custom options into the configuration file or even use another configuration # file. strategy = VolatilityMarketMaker( symbol=Symbol("ETH/USDT", Venue("BINANCE")), bar_spec=time_bars, trade_size=Decimal("0.05"), atr_period=20, atr_multiple=1.0, order_id_tag="001", )