Files
ai/sandbox/RESEARCH_API_USAGE.md

7.7 KiB

Research Script API Usage

Research scripts executed via the ExecuteResearch MCP tool have access to the global API instance, which provides both data fetching and charting capabilities.

Accessing the API

from dexorder.api import get_api
import asyncio

# Get the global API instance
api = get_api()

Using the Data API

The data API provides access to historical OHLC (Open, High, Low, Close) market data with smart caching via Iceberg.

Fetching Historical Data

The API accepts flexible timestamp formats for convenience:

from dexorder.api import get_api
import asyncio
from datetime import datetime

api = get_api()

# Method 1: Using Unix timestamps (seconds)
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,  # 1 hour candles
    start_time=1640000000,  # Unix timestamp in seconds
    end_time=1640086400,
    extra_columns=["volume"]
))

# Method 2: Using date strings
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,
    start_time="2021-12-20",  # Simple date string
    end_time="2021-12-21",
    extra_columns=["volume"]
))

# Method 3: Using date strings with time
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,
    start_time="2021-12-20 00:00:00",
    end_time="2021-12-20 23:59:59",
    extra_columns=["volume"]
))

# Method 4: Using datetime objects
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,
    start_time=datetime(2021, 12, 20),
    end_time=datetime(2021, 12, 21),
    extra_columns=["volume"]
))

print(f"Loaded {len(df)} candles")
print(df.head())

Available Extra Columns

  • "volume" - Total volume
  • "buy_vol" - Buy-side volume
  • "sell_vol" - Sell-side volume
  • "open_time", "high_time", "low_time", "close_time" - Timestamps for each price point
  • "open_interest" - Open interest (for futures)
  • "ticker" - Market identifier
  • "period_seconds" - Period in seconds

Building a Scanner Universe with get_ticker_24h

Always pre-filter symbols before fetching OHLC for multiple tickers. The per-script bar budget is 2M bars; fetching all ~1800 Binance symbols would exhaust it immediately. Use get_ticker_24h to get a ranked, filtered list of symbols with no OHLC budget cost, then run per-symbol analysis only on the filtered set.

from dexorder.api import get_api
import asyncio

api = get_api()

# Get top 50 most liquid Binance spot symbols by USD volume (no bar budget used)
universe = asyncio.run(api.data.get_ticker_24h(
    "BINANCE",
    limit=50,
    market_type="spot",
    min_std_quote_volume=10_000_000  # filter to $10M+ daily USD volume
))
print(f"Universe: {len(universe)} symbols")

# Now fetch OHLC only for the filtered set
for ticker in universe["ticker"]:
    df = asyncio.run(api.data.historical_ohlc(
        ticker=ticker,
        period_seconds=86400,  # daily bars for a scanner
        start_time="2024-01-01",
        end_time="2025-01-01",
        extra_columns=["volume"]
    ))
    print(f"[Data] {ticker}: {len(df)} bars")

Filter parameters

# All BTC pairs on Binance
df = asyncio.run(api.data.get_ticker_24h("BINANCE", base_asset_contains="BTC"))

# Top 100 perp markets with $50M+ daily volume
df = asyncio.run(api.data.get_ticker_24h(
    "BINANCE", limit=100, market_type="perp", min_std_quote_volume=50_000_000
))

# All symbols on Coinbase
df = asyncio.run(api.data.get_ticker_24h("COINBASE"))

Returned DataFrame is sorted by std_quote_volume (USD-normalized) descending. Symbols without a USD rate have std_quote_volume = NaN and appear last. Full column list: ticker, exchange_id, base_asset, quote_asset, last_price, price_change_pct, quote_volume_24h, std_quote_volume, bid_price, ask_price, open_24h, high_24h, low_24h, volume_24h, num_trades, timestamp_ms.

Using the Charting API

The charting API provides styled financial charts with OHLC candlesticks and technical indicators.

Creating a Basic Candlestick Chart

from dexorder.api import get_api
import asyncio
from datetime import datetime

api = get_api()

# Fetch data
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,
    start_time="2021-12-20",
    end_time="2021-12-21",
    extra_columns=["volume"]
))

# Create candlestick chart (synchronous)
fig, ax = api.charting.plot_ohlc(
    df,
    title="BTC/USDT 1H",
    volume=True,  # Show volume bars
    style="charles"  # Chart style
)

# The figure is automatically captured and returned to the MCP client

Adding Indicator Panels

from dexorder.api import get_api
import asyncio
import pandas as pd

api = get_api()

# Fetch data
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,
    start_time="2021-12-20",
    end_time="2021-12-21"
))

# Calculate a simple moving average
df['sma_20'] = df['close'].rolling(window=20).mean()

# Create chart
fig, ax = api.charting.plot_ohlc(df, title="BTC/USDT with SMA")

# Overlay the SMA on the price chart
ax.plot(df.index, df['sma_20'], label="SMA 20", color="blue", linewidth=2)
ax.legend()

# Add RSI indicator panel below
df['rsi'] = calculate_rsi(df['close'], 14)  # Your RSI calculation
rsi_ax = api.charting.add_indicator_panel(
    fig, df,
    columns=["rsi"],
    ylabel="RSI",
    ylim=(0, 100)
)
rsi_ax.axhline(70, color='red', linestyle='--', alpha=0.5)
rsi_ax.axhline(30, color='green', linestyle='--', alpha=0.5)

Complete Example

from dexorder.api import get_api
import asyncio
import pandas as pd

# Get API instance
api = get_api()

# Fetch historical data using date strings (easiest for research)
df = asyncio.run(api.data.historical_ohlc(
    ticker="BTC/USDT.BINANCE",
    period_seconds=3600,  # 1 hour
    start_time="2021-12-20",
    end_time="2021-12-21",
    extra_columns=["volume"]
))

# Add some analysis
df['sma_20'] = df['close'].rolling(window=20).mean()
df['sma_50'] = df['close'].rolling(window=50).mean()

# Create chart with volume
fig, ax = api.charting.plot_ohlc(
    df,
    title="BTC/USDT Analysis",
    volume=True,
    style="charles"
)

# Overlay moving averages
ax.plot(df.index, df['sma_20'], label="SMA 20", color="blue", linewidth=1.5)
ax.plot(df.index, df['sma_50'], label="SMA 50", color="red", linewidth=1.5)
ax.legend()

# Print summary statistics
print(f"Period: {len(df)} candles")
print(f"High: {df['high'].max()}")
print(f"Low: {df['low'].min()}")
print(f"Mean Volume: {df['volume'].mean():.2f}")

Notes

  • Async vs Sync: Data API methods are async and require asyncio.run(). Charting API methods are synchronous.
  • Figure Capture: All matplotlib figures created during script execution are automatically captured and returned as PNG images.
  • Print Statements: All print() output is captured and returned as text content.
  • Errors: Exceptions are caught and reported in the execution results.
  • Timestamps: The API accepts flexible timestamp formats:
    • Unix timestamps in seconds (int or float) - e.g., 1640000000
    • Date strings - e.g., "2021-12-20" or "2021-12-20 12:00:00"
    • datetime objects - e.g., datetime(2021, 12, 20)
    • pandas Timestamp objects
    • Internally, the system uses microseconds since epoch, but you don't need to worry about this conversion.
  • Price/Volume Values: All prices and volumes are returned as decimal floats, automatically converted from internal storage format using market metadata. No manual conversion is needed.

Available Chart Styles

  • "charles" (default)
  • "binance"
  • "blueskies"
  • "brasil"
  • "checkers"
  • "classic"
  • "mike"
  • "nightclouds"
  • "sas"
  • "starsandstripes"
  • "yahoo"