Adapters - Loren1166/NautilusTrader- GitHub Wiki

Adapters 适配器

The NautilusTrader design integrates data providers and/or trading venues through adapter implementations, these can be found in the top level adapters subpackage.

NautilusTrader 设计通过适配器实现集成了数据提供程序和/或交易平台,这些可以在顶层 adapters 子包中找到。

An integrations adapter is typically comprised of the following main components:

集成适配器通常由以下主要组件组成:

  • HttpClient HTTP 客户端
  • WebSocketClient WebSocket 客户端
  • InstrumentProvider Instrument适配器
  • DataClient 数据客户端
  • ExecutionClient 执行客户端

Instrument providers Instrument适配器

Instrument providers do as their name suggests - instantiating Nautilus Instrument objects by parsing the publisher or venues raw API.

Instrument适配器顾名思义 - 通过解析发布者或交易平台的原始 API 来实例化 Nautilus Instrument 对象。

The use cases for the instruments available from an InstrumentProvider are either:

InstrumentProvider 提供的Instrument的用例是:

  • Used standalone to discover the instruments available for an integration, using these for research or backtesting purposes. 独立使用以发现集成可用的Instrument,将它们用于研究或回测目的。
  • Used in a sandbox or live environment context for consumption by actors/strategies. 在沙盒或实时环境上下文中使用,供参与者/策略使用。

Research and backtesting 研究和回测

Here is an example of discovering the current instruments for the Binance Futures testnet:

以下是发现 Binance Futures 测试网当前Instrument的示例:

from nautilus_trader.adapters.binance.common.enums import BinanceAccountType
from nautilus_trader.adapters.binance.factories import get_cached_binance_http_client
from nautilus_trader.adapters.binance.futures.providers import BinanceFuturesInstrumentProvider
from nautilus_trader.common.component import LiveClock


clock = LiveClock()
account_type = BinanceAccountType.USDT_FUTURE

client = get_cached_binance_http_client(
    loop=asyncio.get_event_loop(),
    clock=clock,
    account_type=account_type,
    key=os.getenv("BINANCE_FUTURES_TESTNET_API_KEY"),
    secret=os.getenv("BINANCE_FUTURES_TESTNET_API_SECRET"),
    is_testnet=True,
)
await client.connect()

provider = BinanceFuturesInstrumentProvider(
    client=client,
    account_type=BinanceAccountType.USDT_FUTURE,
)

await provider.load_all_async()

Live trading 实时交易

Each integration is implementation specific, and there are generally two options for the behavior of an InstrumentProvider within a TradingNode for live trading, as configured:

每个集成都特定于实现,并且对于实时交易中 TradingNode 内的 InstrumentProvider 的行为,通常有两个选项,如下配置:

All instruments are automatically loaded on start:

启动时自动加载所有Instrument:

from nautilus_trader.config import InstrumentProviderConfig

InstrumentProviderConfig(load_all=True)

Only those instruments explicitly specified in the configuration are loaded on start:

启动时仅加载配置中明确指定的Instrument:

InstrumentProviderConfig(load_ids=["BTCUSDT-PERP.BINANCE", "ETHUSDT-PERP.BINANCE"])

Data clients 数据客户端

Requests 请求

An Actor or Strategy can request custom data from a DataClient by sending a DataRequest. If the client that receives the DataRequest implements a handler for the request, data will be returned to the Actor or Strategy.

ActorStrategy 可以通过发送 DataRequestDataClient 请求自定义数据。如果接收 DataRequest 的客户端实现了请求的处理程序,则数据将返回到 ActorStrategy

Example 例子

An example of this is a DataRequest for an Instrument, which the Actor class implements (copied below). Any Actor or Strategy can call a request_instrument method with an InstrumentId to request the instrument from a DataClient.

这方面的一个例子是 InstrumentDataRequestActor 类实现了它(如下所示)。任何 ActorStrategy 都可以使用 InstrumentId 调用 request_instrument 方法从 DataClient 请求Instrument。

In this particular case, the Actor implements a separate method request_instrument. A similar type of DataRequest could be instantiated and called from anywhere and/or anytime in the actor/strategy code.

在这种特殊情况下,Actor 实现了一个单独的方法 request_instrument。类似类型的 DataRequest 可以在参与者/策略代码中的任何位置和/或任何时间实例化和调用。

On the actor/strategy:

在参与者/策略上:

# nautilus_trader/common/actor.pyx

cpdef void request_instrument(self, InstrumentId instrument_id, ClientId client_id=None):
    """
    Request `Instrument` data for the given instrument ID.

    Parameters
    ----------
    instrument_id : InstrumentId
        The instrument ID for the request.
    client_id : ClientId, optional
        The specific client ID for the command.
        If ``None`` then will be inferred from the venue in the instrument ID.

    """
    Condition.not_none(instrument_id, "instrument_id")

    cdef DataRequest request = DataRequest(
        client_id=client_id,
        venue=instrument_id.venue,
        data_type=DataType(Instrument, metadata={
            "instrument_id": instrument_id,
        }),
        callback=self._handle_instrument_response,
        request_id=UUID4(),
        ts_init=self._clock.timestamp_ns(),
    )

    self._send_data_req(request)

The handler on the ExecutionClient:

ExecutionClient 上的处理程序:

from nautilus_trader.core.uuid import UUID4
from nautilus_trader.model.data import DataType
from nautilus_trader.model.identifiers import InstrumentId

# nautilus_trader/adapters/binance/spot/data.py
def request_instrument(self, instrument_id: InstrumentId, correlation_id: UUID4):
    instrument: Instrument | None = self._instrument_provider.find(instrument_id)
    if instrument is None:
        self._log.error(f"Cannot find instrument for {instrument_id}.")
        return

    data_type = DataType(
        type=Instrument,
        metadata={"instrument_id": instrument_id},
    )

    self._handle_data_response(
        data_type=data_type,
        data=[instrument],  # Data engine handles lists of instruments
        correlation_id=correlation_id,
    )