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 Symbol from nautilus_trader.model.identifiers import TraderId from nautilus_trader.model.identifiers import Venue from nautilus_trader.model.tick import TradeTick from nautilus_trader.trading.portfolio import Portfolio from tests import PACKAGE_ROOT from tests.test_kit.mocks import ObjectStorer from tests.test_kit.stubs import TestStubs TEST_PATH = PACKAGE_ROOT + "/integration_tests/adapters/ccxt/responses/" BINANCE = Venue("BINANCE") BTCUSDT = Symbol("BTC/USDT", BINANCE) ETHUSDT = Symbol("ETH/USDT", BINANCE) # Monkey patch magic mock # This allows the stubbing of calls to coroutines MagicMock.__await__ = lambda x: async_magic().__await__() # Dummy method for above async def async_magic(): return class CCXTDataClientTests(unittest.TestCase): def setUp(self): # Fixture Setup
def ethusd_bitmex_id() -> InstrumentId: return InstrumentId(Symbol("ETH/USD"), Venue("BITMEX"))
def ethusdt_binance_id() -> InstrumentId: return InstrumentId(Symbol("ETH/USDT"), Venue("BINANCE"))
def gbpusd_id() -> InstrumentId: return InstrumentId(Symbol("GBP/USD"), Venue("SIM"))
class BidAskMinMaxTests(unittest.TestCase): instrument_id = InstrumentId(Symbol("SPY"), Venue("NYSE")) def test_instantiate(self): # Arrange indicator = BidAskMinMax(self.instrument_id, timedelta(minutes=5)) # Act # Assert self.assertEqual(None, indicator.bids.min_price) self.assertEqual(None, indicator.bids.max_price) self.assertEqual(None, indicator.asks.min_price) self.assertEqual(None, indicator.asks.max_price) self.assertEqual(False, indicator.initialized) def test_handle_quote_tick(self): # Arrange indicator = BidAskMinMax(self.instrument_id, timedelta(minutes=5)) # Act indicator.handle_quote_tick( QuoteTick( self.instrument_id, Price("1.0"), Price("2.0"), Quantity(1), Quantity(1), datetime(2020, 1, 1, 0, 0, 0, tzinfo=pytz.utc), )) # 5 min later (still in the window) indicator.handle_quote_tick( QuoteTick( self.instrument_id, Price("0.9"), Price("2.1"), Quantity(1), Quantity(1), datetime(2020, 1, 1, 0, 5, 0, tzinfo=pytz.utc), )) # Assert self.assertEqual(Price("0.9"), indicator.bids.min_price) self.assertEqual(Price("1.0"), indicator.bids.max_price) self.assertEqual(Price("2.1"), indicator.asks.min_price) self.assertEqual(Price("2.1"), indicator.asks.max_price) def test_reset(self): # Arrange indicator = BidAskMinMax(self.instrument_id, timedelta(minutes=5)) indicator.handle_quote_tick( QuoteTick( self.instrument_id, Price("0.9"), Price("2.1"), Quantity(1), Quantity(1), datetime(2020, 1, 1, 0, 5, 0, tzinfo=pytz.utc), )) # Act indicator.reset() # Assert self.assertIsNone(indicator.bids.min_price) self.assertIsNone(indicator.asks.min_price)
# limitations under the License. # ------------------------------------------------------------------------------------------------- import unittest from nautilus_trader.execution.base import ExecutionCacheFacade from nautilus_trader.model.identifiers import AccountId from nautilus_trader.model.identifiers import ClientOrderId from nautilus_trader.model.identifiers import PositionId from nautilus_trader.model.identifiers import Symbol from nautilus_trader.model.identifiers import Venue from tests.test_kit.providers import TestInstrumentProvider SIM = Venue("SIM") USDJPY_SIM = TestInstrumentProvider.default_fx_ccy(Symbol("USD/JPY", SIM)) AUDUSD_SIM = TestInstrumentProvider.default_fx_ccy(Symbol("AUD/USD", SIM)) class ExecutionCacheFacadeTests(unittest.TestCase): def setUp(self): # Fixture Setup self.facade = ExecutionCacheFacade() def test_account_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.facade.account, AccountId("SIM", "000")) def test_account_for_venue_when_not_implemented_raises_exception(self): self.assertRaises(NotImplementedError, self.facade.account_for_venue, SIM)
from nautilus_trader.model.objects import Price from nautilus_trader.model.objects import Quantity from nautilus_trader.model.position import Position from nautilus_trader.model.tick import QuoteTick from nautilus_trader.trading.account import Account from nautilus_trader.trading.portfolio import Portfolio from nautilus_trader.trading.portfolio import PortfolioFacade from tests.test_kit.providers import TestInstrumentProvider from tests.test_kit.stubs import TestStubs from tests.test_kit.stubs import UNIX_EPOCH SIM = Venue("SIM") BINANCE = Venue("BINANCE") BITMEX = Venue("BITMEX") AUDUSD_SIM = TestInstrumentProvider.default_fx_ccy(Symbol( "AUD/USD", Venue("SIM")), leverage=Decimal("50")) GBPUSD_SIM = TestInstrumentProvider.default_fx_ccy(Symbol( "GBP/USD", Venue("SIM")), leverage=Decimal("50")) USDJPY_SIM = TestInstrumentProvider.default_fx_ccy(Symbol( "USD/JPY", Venue("SIM")), leverage=Decimal("50")) BTCUSDT_BINANCE = TestInstrumentProvider.btcusdt_binance() BTCUSD_BITMEX = TestInstrumentProvider.xbtusd_bitmex(leverage=Decimal("10")) ETHUSD_BITMEX = TestInstrumentProvider.ethusd_bitmex(leverage=Decimal("10")) class PortfolioFacadeTests(unittest.TestCase): def test_account_raises_not_implemented_error(self): # Arrange
"account_id": "BITMEX_ACCOUNT_ID", # value is the environment variable key "api_key": "BITMEX_API_KEY", # value is the environment variable key "api_secret": "BITMEX_API_SECRET", # value is the environment variable key }, }, } # Instantiate your strategies to pass into the trading node. You could add # custom options into the configuration file or even use another configuration # file. instrument1 = InstrumentId( symbol=Symbol("ETH/USDT"), venue=Venue("BINANCE"), ) strategy1 = EMACross( instrument_id=instrument1, bar_spec=BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST), trade_size=Decimal("0.02"), fast_ema_period=10, slow_ema_period=20, order_id_tag="003", ) # ------------------------------------------------------------------------------ instrument2 = InstrumentId(
def default_fx_ccy(symbol: str, venue: Venue = None) -> CurrencySpot: """ Return a default FX currency pair instrument from the given instrument_id. Parameters ---------- symbol : str The currency pair symbol. venue : Venue The currency pair venue. Returns ------- CurrencySpot Raises ------ ValueError If the instrument_id.instrument_id length is not in range [6, 7]. """ if venue is None: venue = Venue("SIM") PyCondition.valid_string(symbol, "symbol") PyCondition.in_range_int(len(symbol), 6, 7, "len(symbol)") instrument_id = InstrumentId( symbol=Symbol(symbol), venue=venue, ) base_currency = symbol[:3] quote_currency = symbol[-3:] # Check tick precision of quote currency if quote_currency == "JPY": price_precision = 3 else: price_precision = 5 return CurrencySpot( instrument_id=instrument_id, base_currency=Currency.from_str(base_currency), quote_currency=Currency.from_str(quote_currency), price_precision=price_precision, size_precision=0, price_increment=Price(1 / 10**price_precision, price_precision), size_increment=Quantity.from_int(1), lot_size=Quantity.from_str("1000"), max_quantity=Quantity.from_str("1e7"), min_quantity=Quantity.from_str("1000"), max_price=None, min_price=None, max_notional=Money(50000000.00, USD), min_notional=Money(1000.00, USD), margin_init=Decimal("0.03"), margin_maint=Decimal("0.03"), maker_fee=Decimal("0.00002"), taker_fee=Decimal("0.00002"), timestamp_origin_ns=0, timestamp_ns=0, )
# 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 = EMACross( symbol=Symbol("ETH/USDT", Venue("BINANCE")), bar_spec=time_bars, 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:
"BITMEX_ACCOUNT_ID", # value is the environment variable key "api_key": "BITMEX_API_KEY", # value is the environment variable key "api_secret": "BITMEX_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. instrument_id = InstrumentId( symbol=Symbol("BTC/USD"), venue=Venue("BITMEX"), ) strategy = EMACross( instrument_id=instrument_id, bar_spec=BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST), fast_ema_period=10, slow_ema_period=20, trade_size=Decimal("10"), order_id_tag="002", ) # Instantiate the node passing a list of strategies and configuration node = TradingNode(strategies=[strategy], config=config)
"exec_client": True, # If a exec client should be created "account_id": "BITMEX_ACCOUNT_ID", # value is the environment variable key "api_key": "BITMEX_API_KEY", # value is the environment variable key "api_secret": "BITMEX_API_SECRET", # value is the environment variable key }, }, } # Instantiate your strategies to pass into the trading node. You could add # custom options into the configuration file or even use another configuration # file. strategy1 = EMACross( symbol=Symbol("ETH/USDT", Venue("BINANCE")), bar_spec=BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST), trade_size=Decimal("0.02"), fast_ema_period=10, slow_ema_period=20, order_id_tag="003", ) strategy2 = EMACrossStopEntryTrail( symbol=Symbol("BTC/USD", Venue("BITMEX")), bar_spec=BarSpecification(1, BarAggregation.MINUTE, PriceType.LAST), trade_size=Decimal("100"), fast_ema_period=10, slow_ema_period=20, atr_period=20, trail_atr_multiple=2.0,
"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. instrument_id = InstrumentId( symbol=Symbol("ETH/USDT"), venue=Venue("BINANCE"), ) strategy = EMACross( instrument_id=instrument_id, 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)
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 "AUD/USD.SIM-1-MINUTE-BID" == str(bar_type) assert "BarType(AUD/USD.SIM-1-MINUTE-BID, internal_aggregation=True)" == repr( bar_type) @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 bar_type == expected
def symbol_gbpusd_fxcm() -> Symbol: return Symbol("GBP/USD", Venue("SIM"))
def instrument_id(): return InstrumentId(symbol=Symbol("Test"), venue=BETFAIR_VENUE)
def symbol_usdjpy_fxcm() -> Symbol: return Symbol("USD/JPY", Venue("SIM"))
# See the License for the specific language governing permissions and # limitations under the License. # ------------------------------------------------------------------------------------------------- import unittest from nautilus_trader.core.message import Message from nautilus_trader.core.message import MessageType from nautilus_trader.core.uuid import uuid4 from nautilus_trader.model.commands import SubmitOrder from nautilus_trader.model.identifiers import InstrumentId from nautilus_trader.model.identifiers import Symbol from nautilus_trader.model.identifiers import Venue from tests.test_kit.performance import PerformanceHarness AUDUSD = InstrumentId(Symbol("AUDUSD"), Venue("IDEALPRO")) MESSAGE = Message(MessageType.COMMAND, uuid4(), 0) class Experiments: @staticmethod def built_in_arithmetic(): x = 1 + 1 return x @staticmethod def class_name(): x = "123".__class__.__name__ return x @staticmethod
# 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 = EMACross( symbol=Symbol("BTC/USD", Venue("BITMEX")), bar_spec=time_bars, fast_ema_period=10, slow_ema_period=20, trade_size=Decimal("10"), ) # 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 symbol_btcusd_bitmex() -> Symbol: return Symbol("BTC/USD", Venue("BITMEX"))
def usdjpy_id() -> InstrumentId: return InstrumentId(Symbol("USD/JPY"), Venue("SIM"))
def symbol_ethusd_bitmex() -> Symbol: return Symbol("ETH/USD", Venue("BITMEX"))
from nautilus_trader.model.enums import OMSType from nautilus_trader.model.enums import PriceType from nautilus_trader.model.identifiers import Symbol from nautilus_trader.model.identifiers import Venue from nautilus_trader.model.objects import Money from tests.test_kit.providers import TestDataProvider if __name__ == "__main__": # Setup trading instruments # Requires an internet connection for the instrument loader # Alternatively use the TestInstrumentProvider in the test kit print("Loading instruments...") instruments = CCXTInstrumentProvider(client=ccxt.binance(), load_all=True) BINANCE = Venue("BINANCE") ETHUSDT_BINANCE = instruments.get(Symbol("ETH/USDT", BINANCE)) # Setup data container data = BacktestDataContainer() data.add_instrument(ETHUSDT_BINANCE) data.add_trade_ticks(ETHUSDT_BINANCE.symbol, TestDataProvider.ethusdt_trades()) # Instantiate your strategy strategy = EMACross( symbol=ETHUSDT_BINANCE.symbol, bar_spec=BarSpecification(250, BarAggregation.TICK, PriceType.LAST), fast_ema_period=10, slow_ema_period=20, trade_size=Decimal(100), order_id_tag="001",
def symbol_btcusdt_binance() -> Symbol: return Symbol("BTC/USDT", Venue("BINANCE"))
def btcusd_bitmex_id() -> InstrumentId: return InstrumentId(Symbol("BTC/USD"), Venue("BITMEX"))
def symbol_ethusdt_binance() -> Symbol: return Symbol("ETH/USDT", Venue("BINANCE"))
def btcusdt_binance_id() -> InstrumentId: return InstrumentId(Symbol("BTC/USDT"), Venue("BINANCE"))
def symbol_audusd_fxcm() -> Symbol: return Symbol("AUD/USD", Venue("SIM"))
def audusd_id() -> InstrumentId: return InstrumentId(Symbol("AUD/USD"), Venue("SIM"))
class BarTypeTests(unittest.TestCase): def test_bar_type_equality(self): # Arrange symbol1 = Symbol("AUD/USD", Venue("SIM")) symbol2 = Symbol("GBP/USD", Venue("SIM")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type1 = BarType(symbol1, bar_spec) bar_type2 = BarType(symbol1, bar_spec) bar_type3 = BarType(symbol2, bar_spec) # Act # Assert self.assertTrue(bar_type1 == bar_type1) self.assertTrue(bar_type1 == bar_type2) self.assertTrue(bar_type1 != bar_type3) def test_bar_type_str_and_repr(self): # Arrange symbol = Symbol("AUD/USD", Venue("SIM")) bar_spec = BarSpecification(1, BarAggregation.MINUTE, PriceType.BID) bar_type = BarType(symbol, bar_spec) # Act # Assert self.assertEqual("AUD/USD.SIM-1-MINUTE-BID", str(bar_type)) self.assertEqual( "BarType(AUD/USD.SIM-1-MINUTE-BID, internal_aggregation=True)", repr(bar_type)) @parameterized.expand([ [""], ["AUD/USD"], ["AUD/USD.IDEALPRO-1-MILLISECOND-BID"], ]) def test_from_str_given_various_invalid_strings_raises_value_error( self, value): # Arrange # Act # Assert self.assertRaises(ValueError, BarType.from_str, value) @parameterized.expand([ [ "AUD/USD.IDEALPRO-1-MINUTE-BID", BarType(Symbol("AUD/USD", Venue("IDEALPRO")), BarSpecification(1, BarAggregation.MINUTE, PriceType.BID)) ], [ "GBP/USD.SIM-1000-TICK-MID", BarType(Symbol("GBP/USD", Venue("SIM")), BarSpecification(1000, BarAggregation.TICK, PriceType.MID)) ], [ "AAPL.NYSE-1-HOUR-MID", BarType(Symbol("AAPL", Venue("NYSE")), BarSpecification(1, BarAggregation.HOUR, PriceType.MID)) ], [ "BTC/USDT.BINANCE-100-TICK-LAST", BarType(Symbol("BTC/USDT", Venue("BINANCE")), BarSpecification(100, BarAggregation.TICK, PriceType.LAST)) ], ]) def test_from_str_given_various_valid_string_returns_expected_specification( self, value, expected): # Arrange # Act bar_type = BarType.from_str(value, internal_aggregation=True) # Assert self.assertEqual(bar_type, expected)