Skip to main content

Hunter quant bot framework Python bindings

Project description

hunter-quant

Python bindings for the Hunter quant trading framework. Built with PyO3 + maturin for high-performance live trading, sandbox, and backtesting.

Installation

uv add hunter-quant

For projects that do not use uv:

pip install hunter-quant

Development

cd bindings/python
uv sync --extra dev
uv run maturin develop
uv run pytest

Static stub synchronization can be checked without installing the extension:

uv run python bindings/python/scripts/check_pyi_sync.py

Release steps are documented in docs/release.md.

Examples

Runnable strategy examples live in examples/:

  • examples/sma_cross.py
  • examples/supertrend_risk.py

Install the extension into your active environment before running examples:

cd bindings/python
uv run maturin develop
uv run python examples/sma_cross.py

Quality Gates

cargo fmt -p python
cargo check -p python
cargo test -p python
uv run python bindings/python/scripts/check_pyi_sync.py

After maturin develop, run Python smoke tests:

cd bindings/python
uv run maturin develop
uv run pytest

Quick Start

import hunter
from hunter import Strategy


class MyStrategy(Strategy):
    def __init__(self):
        self.btc = self.candles(connector_id="hyperliquid_perp", symbol="BTC-USDC", timeframe="15m")
        self.broker = self.broker(connector_id="hyperliquid_perp", address = "", private_key = "", rate_limit = 1200 )

    def on_bar(self):
        close = self.btc.close
        fast = hunter.ta.sma(close, 7)
        slow = hunter.ta.sma(close, 25)

        if fast.cross_over(slow):
            self.broker.market_buy("BTC-USDC", 0.01)
        elif fast.cross_under(slow):
            self.broker.market_sell("BTC-USDC", 0.01)

Run Modes

  • "live" — real trading on live exchanges
  • "sandbox" — simulated trading on testnet
  • "backtest" — historical backtesting
hunter.run(MyStrategy(), mode="backtest")
hunter.run(MyStrategy(), mode="sandbox")
hunter.run(MyStrategy(), mode="live")

Feeds

CandleFeed

feed = self.candles(connector_id="hyperliquid_perp", symbol="BTC-USDC", timeframe="15m", warmup_period=200)

Properties/Methods:

  • dataframe — polars DataFrame
  • open, high, low, close, volume, start_time — shortcut to each column as Series

OrderBookFeed

feed = self.orderbook(connector_id="hyperliquid_perp", symbol="BTC-USDC")

Properties: best_bid, best_ask, mid_price, spread, spread_bps, microprice, microprice_offset_bps, bids, asks, top_of_book_imbalance

Methods: cumulative_bid_depth(levels), cumulative_ask_depth(levels), depth_imbalance(levels), depth_pressure(levels, decay)

TradeFeed

feed = self.trades(connector_id="hyperliquid_perp", symbol="BTC-USDC", warmup_period=100)
  • dataframe — polars DataFrame

Series API

series[0]        # latest value (rightmost)
len(series)

series.cross_over(other)
series.cross_under(other)
series.cross(other)
series.to_polars()

TA Module

import hunter

hunter.ta.sma(source, period=20)
hunter.ta.ema(source, period=20)
hunter.ta.rsi(source, period=14)
hunter.ta.bollinger_bands(source, period=20, dev_up=2.0, dev_down=2.0)
hunter.ta.macd(source, fast=12, slow=26, signal=9)
hunter.ta.atr(high, low, close, period=14)
hunter.ta.adx(high, low, close, period=14)
hunter.ta.stoch(high, low, close, k=14, k_slow=3, d=3)
hunter.ta.supertrend(high, low, close, period=10, multiplier=3.0)
hunter.ta.vwap(high, low, close, volume)
hunter.ta.cci(high, low, close, period=20)
hunter.ta.obv(close, volume)
hunter.ta.sar(high, low, acceleration=0.02, maximum=0.2)
hunter.ta.heikin_ashi(open, high, low, close)
hunter.ta.slope(source, n=5)

# Candlestick patterns
hunter.ta.cdl_doji(open, high, low, close, body_percent=0.1)
hunter.ta.cdl_dragonfly_doji(open, high, low, close, body_percent=1.0)
hunter.ta.cdl_gravestone_doji(open, high, low, close, body_percent=1.0)
hunter.ta.cdl_hammer(open, high, low, close, period=20, factor=1.5)
hunter.ta.cdl_inverted_hammer(open, high, low, close, period=20, factor=1.5)
hunter.ta.cdl_long_shadow(open, high, low, close, period=10, shadow_factor=1.5)
hunter.ta.cdl_marubozu(open, high, low, close, period=10, shadow_percent=0.1)

Broker

broker = self.broker(connector_id="hyperliquid_perp")

# Order shortcuts
broker.market_buy("BTC-USDC", 0.01)
broker.market_sell("BTC-USDC", 0.01)
broker.limit_buy("BTC-USDC", 0.01, price=50000)
broker.limit_sell("BTC-USDC", 0.01, price=55000)

# Conditional orders
broker.stop_market_buy("BTC-USDC", 0.01, trigger_price=51000)
broker.take_profit_market_sell("BTC-USDC", 0.01, trigger_price=60000)
broker.stop_limit_buy("BTC-USDC", 0.01, trigger_price=51000, limit_price=51200)
broker.take_profit_limit_sell("BTC-USDC", 0.01, trigger_price=60000, limit_price=59000)

# Batch orders
broker.place_orders([
    {"symbol": "BTC-USDC", "side": "buy", "quantity": 0.01, "order_type": "market"},
    {"symbol": "BTC-USDC", "side": "sell", "quantity": 0.01, "order_type": "limit", "price": 60000},
])

# Order management
broker.get_order(order_id)
broker.get_opened_orders("BTC-USDC")
broker.get_orders()
broker.get_order_by_client_id("my-client-id")
broker.cancel_order(order_id)
broker.cancel_orders([id1, id2])

# Positions
position = broker.get_position("BTC-USDC")
position.unrealized_pnl(current_price=55000)
position.unrealized_pnl_percentage(current_price=55000)
broker.get_positions()
broker.close_position("BTC-USDC")
broker.get_orders_in_position("BTC-USDC")

# Stop loss / take profit
broker.with_stop_loss("BTC-USDC", price=48000)
broker.with_take_profit("BTC-USDC", price=65000)
broker.stop_loss_price("BTC-USDC")
broker.take_profit_price("BTC-USDC")
broker.clear_stop_loss("BTC-USDC")
broker.clear_take_profit("BTC-USDC")

# Market info
market = broker.get_market("BTC-USDC")
market.align_price(50000.123)
market.align_quantity(0.012345)

# Status
broker.running_status()
broker.current_price("BTC-USDC")

Risk Rules

Before-order rules

from hunter import MaxNetPositionRule, StopLossPauseRule, OrderSizeRule

strategy.add_before_order_rule(
    MaxNetPositionRule(max_abs_position_size=1.5),
    StopLossPauseRule(stop_loss_pause_mins=60, max_loss_nums=3),
    OrderSizeRule(min_order_size=0.001, max_order_size=1.0),
)

After-order rules

from hunter import OrderTimeoutRule, MaxDrawdownRule

strategy.add_after_order_rule(
    OrderTimeoutRule(timeout_secs=300),
    MaxDrawdownRule(drawdown_limit=0.1, limit_type="amount"),
)

Notifier

from hunter import Notifier

strategy.add_notifier(Notifier.logger(level="info"))
strategy.add_notifier(Notifier.telegram(token="xxx", recipients=[123456789]))
strategy.add_notifier(Notifier.dingtalk(token="xxx", secret=None))
strategy.add_notifier(
    Notifier.email(
        username="u@example.com",
        password="xxx",
        server="smtp.example.com",
        from_="u@example.com",
        recipients=["alerts@example.com"],
    )
)

# Send notification within a strategy
self.notify("Subject", "Message body")

Callbacks

class MyStrategy(Strategy):
    def on_ready(self):              # strategy initialized
    def on_bar(self):                # new candle
    def on_orderbook(self):          # orderbook updated
    def on_trade(self):              # trade occurred
    def on_order_update(self, order):  # order status changed
    def on_stop(self):               # strategy stopped

Callbacks must be synchronous functions. async def callbacks are rejected at runtime.

Event Objects

# Bar
bar.feed, bar.symbol, bar.interval
bar.open, bar.high, bar.low, bar.close, bar.volume, bar.timestamp

# OrderBook
ob.symbol, ob.best_bid, ob.best_ask, ob.spread, ob.microprice

# Trade
trade.symbol, trade.price, trade.quantity, trade.side, trade.timestamp

# Fill
fill.fill_id, fill.order_id, fill.price, fill.quantity

# Order
order.id, order.symbol, order.side, order.order_type
order.quantity, order.executed_quantity, order.average_price
order.status, order.created_at, order.updated_at

# Position
position.symbol, position.side, position.quantity, position.average_price
position.unrealized_pnl(current_price)
position.unrealized_pnl_percentage(current_price)

Backtest Example

import hunter
from hunter import Strategy


class SupertrendCross(Strategy):
    def __init__(self):
        self.btc = self.candles(
            connector_id="hyperliquid_perp", symbol="BTC-USDC", timeframe="15m",
        )
        self.broker = self.broker(connector_id="hyperliquid_perp")
        self.with_trailing_stop(3600)

    def on_bar(self):
        st = hunter.ta.supertrend(self.btc.high, self.btc.low, self.btc.close, 10, 3.0)

        if st.trend.cross_over(st.line):
            self.broker.market_buy("BTC-USDC", 0.01)
        elif st.trend.cross_under(st.line):
            self.broker.market_sell("BTC-USDC", 0.01)


hunter.run(SupertrendCross(), mode="backtest")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

hunter_quant-0.1.3-cp314-cp314-macosx_11_0_arm64.whl (8.9 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

hunter_quant-0.1.3-cp312-cp312-win_amd64.whl (9.2 MB view details)

Uploaded CPython 3.12Windows x86-64

hunter_quant-0.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.5 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

File details

Details for the file hunter_quant-0.1.3-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hunter_quant-0.1.3-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b0939b1bd130b830866237271ff9bba181e8bb263829f574ddff58775ca9357d
MD5 81d5a07de63ceda39805c5e534317df5
BLAKE2b-256 7477395a3015690e038040d6864bd313d01790016a2df9a30fed938fcef847f3

See more details on using hashes here.

File details

Details for the file hunter_quant-0.1.3-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for hunter_quant-0.1.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 02cc91e68aeb8c4845f8e46442c63c771b8587bec0667bce08d6eb271f88916e
MD5 e53685003c6b9ce6b4f1795d88220a5a
BLAKE2b-256 7502b18b91062b70774f335d57837912f83f5aa4bb4a32305f260bc3ad5c2744

See more details on using hashes here.

File details

Details for the file hunter_quant-0.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for hunter_quant-0.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9fd77e142e39e9534a82f7a0490db6ac7d9cac6a8f2c17172f8084ce08f79118
MD5 757b1ae7c1516b46e36a097c8ba3a3d9
BLAKE2b-256 bd6c7441e5050dee328be63912f540b84a880394ad5c42d74344fe414adb64f2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page