Web Callbacks¶
NexusTrader includes an optional embedded FastAPI web server that lets you expose HTTP endpoints inside your strategy. This is useful for receiving external signals (e.g., from a TradingView webhook or a custom dashboard) without running a separate process.
Enabling the Web Server¶
Set web_config in your Config:
from nexustrader.config import Config, WebConfig
config = Config(
...
web_config=WebConfig(
enabled=True,
host="127.0.0.1",
port=6666,
log_level="error",
),
)
WebConfig Parameters¶
Field |
Type |
Description |
|---|---|---|
|
|
Enable the embedded web server (default: |
|
|
Bind address (default: |
|
|
Listening port (default: |
|
|
Uvicorn log level: |
Defining Endpoints in the Strategy¶
Use the create_strategy_app helper to attach a FastAPI app to your strategy class, then
decorate methods with standard FastAPI decorators. The method receives self (the strategy
instance) so it can read and modify strategy state directly.
from typing import Any
from nexustrader.strategy import Strategy
from nexustrader.web import create_strategy_app
class MyStrategy(Strategy):
web_app = create_strategy_app(title="My Strategy")
def __init__(self):
super().__init__()
self.signal_enabled = False
@web_app.post("/toggle")
async def on_toggle(self, payload: dict[str, Any]) -> dict[str, Any]:
self.signal_enabled = payload.get("enabled", not self.signal_enabled)
self.log.info(f"signal_enabled={self.signal_enabled}")
return {"enabled": self.signal_enabled}
Calling the endpoint:
curl -X POST http://127.0.0.1:6666/toggle \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
Full Example¶
from typing import Any
from nexustrader.config import Config, PublicConnectorConfig, BasicConfig, WebConfig
from nexustrader.constants import ExchangeType
from nexustrader.exchange.binance import BinanceAccountType
from nexustrader.strategy import Strategy
from nexustrader.engine import Engine
from nexustrader.web import create_strategy_app
class BinanceWebCallbackStrategy(Strategy):
"""Exposes a /toggle endpoint to enable or disable the trading signal."""
web_app = create_strategy_app(title="Binance Web Callback")
def __init__(self) -> None:
super().__init__()
self.signal_enabled = False
@web_app.post("/toggle")
async def on_web_cb(self, payload: dict[str, Any]) -> dict[str, Any]:
self.signal_enabled = payload.get("enabled", not self.signal_enabled)
self.log.info(f"Received web callback payload={payload}")
return {"enabled": self.signal_enabled}
config = Config(
strategy_id="binance_web_callback",
user_id="demo_user",
strategy=BinanceWebCallbackStrategy(),
basic_config={
ExchangeType.BINANCE: BasicConfig(testnet=False)
},
public_conn_config={
ExchangeType.BINANCE: [
PublicConnectorConfig(
account_type=BinanceAccountType.USD_M_FUTURE
)
]
},
web_config=WebConfig(
enabled=True,
host="127.0.0.1",
port=6666,
log_level="error",
),
)
engine = Engine(config)
if __name__ == "__main__":
try:
engine.start()
finally:
engine.dispose()
Interactive API Docs¶
When the server is running, FastAPI automatically generates interactive documentation at:
http://<host>:<port>/docs— Swagger UIhttp://<host>:<port>/redoc— ReDoc
Note
The web server runs in a background thread so it does not block the main event loop.
Endpoint handlers are async and run inside the server’s own event loop; avoid
directly awaiting coroutines from the main trading loop inside them.