Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions examples/live/polymarket/polymarket_slug_builder_tester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
# -------------------------------------------------------------------------------------------------
# Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
# https://nautechsystems.io
#
# Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -------------------------------------------------------------------------------------------------
"""
Example TradingNode script demonstrating the event_slug_builder feature.

This script shows how to efficiently load niche Polymarket markets using
dynamically generated event slugs instead of downloading all 151k+ markets.

The event_slug_builder takes a fully qualified path to a callable that returns
a list of event slugs. The provider fetches only those specific events from
the Gamma API.

Usage:
python examples/live/polymarket/polymarket_slug_builder_tester.py

Environment variables required (set these before running):
export POLYMARKET_PK="your_private_key"
export POLYMARKET_API_KEY="your_api_key"
export POLYMARKET_API_SECRET="your_api_secret"
export POLYMARKET_PASSPHRASE="your_passphrase"

To get Polymarket API credentials:
1. Go to https://polymarket.com and connect your wallet
2. Navigate to Settings -> API Keys
3. Create new API credentials

"""

from nautilus_trader.adapters.polymarket import POLYMARKET
from nautilus_trader.adapters.polymarket import PolymarketDataClientConfig
from nautilus_trader.adapters.polymarket import PolymarketLiveDataClientFactory
from nautilus_trader.adapters.polymarket.providers import PolymarketInstrumentProviderConfig
from nautilus_trader.config import LiveExecEngineConfig
from nautilus_trader.config import LoggingConfig
from nautilus_trader.config import TradingNodeConfig
from nautilus_trader.live.node import TradingNode
from nautilus_trader.model.identifiers import TraderId


# Configure the instrument provider with event_slug_builder
# NOTE: load_all=True is required to trigger the provider's load_all_async() method,
# but event_slug_builder takes priority and only loads the specific events.
instrument_config = PolymarketInstrumentProviderConfig(
load_all=True, # Required to trigger loading
event_slug_builder="examples.live.polymarket.slug_builders:build_btc_updown_slugs",
)

# Alternative slug builders you can try:
# - "examples.live.polymarket.slug_builders:build_eth_updown_slugs" # ETH 15-min UpDown
# - "examples.live.polymarket.slug_builders:build_crypto_updown_slugs" # BTC, ETH, SOL
# - "examples.live.polymarket.slug_builders:build_sample_slugs" # Static sample slugs

# Configure the trading node
config_node = TradingNodeConfig(
trader_id=TraderId("SLUG-BUILDER-001"),
logging=LoggingConfig(log_level="INFO", use_pyo3=True),
exec_engine=LiveExecEngineConfig(
reconciliation=False, # Not applicable for data-only
),
data_clients={
POLYMARKET: PolymarketDataClientConfig(
private_key=None, # 'POLYMARKET_PK' env var
api_key=None, # 'POLYMARKET_API_KEY' env var
api_secret=None, # 'POLYMARKET_API_SECRET' env var
passphrase=None, # 'POLYMARKET_PASSPHRASE' env var
instrument_config=instrument_config,
compute_effective_deltas=True,
update_instruments_interval_mins=15, # Refresh every 15 mins for UpDown markets
),
},
timeout_connection=30.0,
timeout_disconnection=10.0,
timeout_post_stop=1.0,
)

# Instantiate the node with a configuration
node = TradingNode(config=config_node)

# Register your client factories with the node
node.add_data_client_factory(POLYMARKET, PolymarketLiveDataClientFactory)
node.build()


# Stop and dispose of the node with SIGINT/CTRL+C
if __name__ == "__main__":
try:
node.run()
finally:
node.dispose()
139 changes: 139 additions & 0 deletions examples/live/polymarket/slug_builders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
# -------------------------------------------------------------------------------------------------
# Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
# https://nautechsystems.io
#
# Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -------------------------------------------------------------------------------------------------
"""
Example slug builder functions for Polymarket event_slug_builder feature.

These functions dynamically generate event slugs for niche markets with
predictable naming patterns, allowing efficient loading without downloading
all 151k+ markets.

Usage:
In your PolymarketInstrumentProviderConfig:
```python
instrument_config = PolymarketInstrumentProviderConfig(
load_all=True,
event_slug_builder="examples.live.polymarket.slug_builders:build_btc_updown_slugs",
)
```

"""

from datetime import UTC
from datetime import datetime
from datetime import timedelta


def build_btc_updown_slugs() -> list[str]:
"""
Build slugs for BTC 15-minute UpDown markets for the next few hours.

UpDown markets follow the pattern: btc-updown-15m-{unix_timestamp}
Where timestamp is the START of the 15-minute window.

Returns
-------
list[str]
List of event slugs for BTC UpDown markets.

"""
slugs = []
now = datetime.now(tz=UTC)

# Round down to nearest 15-minute interval
minutes = (now.minute // 15) * 15
base_time = now.replace(minute=minutes, second=0, microsecond=0)

# Generate slugs for the next 8 intervals (2 hours)
for i in range(8):
interval_time = base_time + timedelta(minutes=15 * i)
timestamp = int(interval_time.timestamp())
slug = f"btc-updown-15m-{timestamp}"
slugs.append(slug)

return slugs


def build_eth_updown_slugs() -> list[str]:
"""
Build slugs for ETH 15-minute UpDown markets for the next few hours.

Returns
-------
list[str]
List of event slugs for ETH UpDown markets.

"""
slugs = []
now = datetime.now(tz=UTC)

# Round down to nearest 15-minute interval
minutes = (now.minute // 15) * 15
base_time = now.replace(minute=minutes, second=0, microsecond=0)

# Generate slugs for the next 8 intervals (2 hours)
for i in range(8):
interval_time = base_time + timedelta(minutes=15 * i)
timestamp = int(interval_time.timestamp())
slug = f"eth-updown-15m-{timestamp}"
slugs.append(slug)

return slugs


def build_crypto_updown_slugs() -> list[str]:
"""
Build slugs for multiple crypto 15-minute UpDown markets (BTC, ETH, SOL).

Returns
-------
list[str]
List of event slugs for crypto UpDown markets.

"""
cryptos = ["btc", "eth", "sol"]
slugs = []
now = datetime.now(tz=UTC)

# Round down to nearest 15-minute interval
minutes = (now.minute // 15) * 15
base_time = now.replace(minute=minutes, second=0, microsecond=0)

# Generate slugs for the next 4 intervals (1 hour) per crypto
for i in range(4):
interval_time = base_time + timedelta(minutes=15 * i)
timestamp = int(interval_time.timestamp())
for crypto in cryptos:
slug = f"{crypto}-updown-15m-{timestamp}"
slugs.append(slug)

return slugs


def build_sample_slugs() -> list[str]:
"""
Build a list of sample slugs for testing.

Returns known active event slugs from Polymarket.

Returns
-------
list[str]
List of sample event slugs.

"""
return [
"presidential-election-winner-2024",
]
7 changes: 7 additions & 0 deletions nautilus_trader/adapters/polymarket/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# -------------------------------------------------------------------------------------------------

from nautilus_trader.adapters.polymarket.common.constants import POLYMARKET_VENUE
from nautilus_trader.adapters.polymarket.providers import PolymarketInstrumentProviderConfig
from nautilus_trader.config import LiveDataClientConfig
from nautilus_trader.config import LiveExecClientConfig
from nautilus_trader.config import PositiveFloat
Expand All @@ -27,6 +28,8 @@ class PolymarketDataClientConfig(LiveDataClientConfig, frozen=True):

Parameters
----------
instrument_config : PolymarketInstrumentProviderConfig, optional
The Polymarket instrument provider config.
venue : Venue, default POLYMARKET_VENUE
The venue for the client.
private_key : str, optional
Expand Down Expand Up @@ -70,6 +73,7 @@ class PolymarketDataClientConfig(LiveDataClientConfig, frozen=True):

"""

instrument_config: PolymarketInstrumentProviderConfig | None = None
venue: Venue = POLYMARKET_VENUE
private_key: str | None = None
signature_type: int = 0
Expand All @@ -93,6 +97,8 @@ class PolymarketExecClientConfig(LiveExecClientConfig, frozen=True):

Parameters
----------
instrument_config : PolymarketInstrumentProviderConfig, optional
The Polymarket instrument provider config.
venue : Venue, default POLYMARKET_VENUE
The venue for the client.
private_key : str, optional
Expand Down Expand Up @@ -143,6 +149,7 @@ class PolymarketExecClientConfig(LiveExecClientConfig, frozen=True):

"""

instrument_config: PolymarketInstrumentProviderConfig | None = None
venue: Venue = POLYMARKET_VENUE
private_key: str | None = None
signature_type: int = 0
Expand Down
10 changes: 5 additions & 5 deletions nautilus_trader/adapters/polymarket/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
from nautilus_trader.adapters.polymarket.data import PolymarketDataClient
from nautilus_trader.adapters.polymarket.execution import PolymarketExecutionClient
from nautilus_trader.adapters.polymarket.providers import PolymarketInstrumentProvider
from nautilus_trader.adapters.polymarket.providers import PolymarketInstrumentProviderConfig
from nautilus_trader.cache.cache import Cache
from nautilus_trader.common.component import LiveClock
from nautilus_trader.common.component import MessageBus
from nautilus_trader.common.config import InstrumentProviderConfig
from nautilus_trader.live.factories import LiveDataClientFactory
from nautilus_trader.live.factories import LiveExecClientFactory

Expand Down Expand Up @@ -100,7 +100,7 @@ def get_polymarket_http_client(
def get_polymarket_instrument_provider(
client: ClobClient,
clock: LiveClock,
config: InstrumentProviderConfig,
config: PolymarketInstrumentProviderConfig | None,
) -> PolymarketInstrumentProvider:
"""
Cache and return a Polymarket instrument provider.
Expand All @@ -113,7 +113,7 @@ def get_polymarket_instrument_provider(
The client for the instrument provider.
clock : LiveClock
The clock for the instrument provider.
config : InstrumentProviderConfig
config : PolymarketInstrumentProviderConfig, optional
The configuration for the instrument provider.

Returns
Expand Down Expand Up @@ -177,7 +177,7 @@ def create( # type: ignore
provider = get_polymarket_instrument_provider(
client=http_client,
clock=clock,
config=config.instrument_provider,
config=config.instrument_config,
)
return PolymarketDataClient(
loop=loop,
Expand Down Expand Up @@ -245,7 +245,7 @@ def create( # type: ignore
provider = get_polymarket_instrument_provider(
client=http_client,
clock=clock,
config=config.instrument_provider,
config=config.instrument_config,
)
return PolymarketExecutionClient(
loop=loop,
Expand Down
Loading
Loading