---
title: "Marketplace"
description: "Sell strategies, subscribe to signals, and purchase strategy packages"
icon: "store"
---

The Horizon Marketplace lets you **monetize your strategies** or **subscribe to proven strategies** from other traders. Revenue split: **90% author, 10% platform fee**, processed via Stripe Connect.

<Note>
Publishing strategies on the marketplace requires the **Ultra** plan. Browsing, subscribing, and purchasing are available on all plans.
</Note>

## Marketplace Modes

<CardGroup cols={2}>
  <Card title="Signal (Copy Trading)" icon="tower-broadcast">
    Your strategy runs on Horizon Cloud. Subscribers receive order signals in real-time **without seeing your code**. Revenue via flat monthly fee.
  </Card>
  <Card title="Package (Direct Sale)" icon="box">
    Buyer purchases your encrypted strategy, receives a license key to decrypt and run locally. Revenue via one-time or licensed sale.
  </Card>
</CardGroup>

## Setup

<Steps>
  <Step title="Install the SDK">
    <CodeGroup>
    ```bash pip
    pip install horizon-sdk
    ```
    ```bash uv
    uv pip install horizon-sdk
    ```
    </CodeGroup>
  </Step>
  <Step title="Set your API key">
    Get your key at [api.mathematicalcompany.com](https://api.mathematicalcompany.com), then:

    ```bash
    export HORIZON_API_KEY="hz_sdk_..."
    ```
  </Step>
  <Step title="Connect payments (authors only)">
    Before publishing paid listings, connect your Stripe account (Ultra plan required):

    ```python
    import horizon as hz

    # Get the Stripe onboarding URL
    result = hz.marketplace.connect_payments()
    print(result["onboarding_url"])  # Complete KYC + bank setup

    # Check status
    status = hz.marketplace.payment_status()
    print(status)  # {"connected": True, "payouts_enabled": True}
    ```
  </Step>
</Steps>

## Browse & Discover

```python
import horizon as hz

# Browse all listings
listings = hz.marketplace.browse()

# Search with filters
listings = hz.marketplace.browse(
    query="btc market making",
    mode="signal",           # "signal" or "package"
    exchange="polymarket",
    sort_by="sharpe",        # "sharpe", "pnl", "subscribers", "price", "newest"
    limit=20,
)

for listing in listings:
    print(f"{listing.name} | Sharpe: {listing.sharpe_ratio:.2f} | "
          f"${listing.price}/mo | {listing.total_subscribers} subs")

# Leaderboard
top = hz.marketplace.leaderboard(timeframe="30d")

# Detailed performance
perf = hz.marketplace.listing_performance("listing-id")
```

## Signal Mode (Copy Trading)

### Publishing

<Steps>
  <Step title="Deploy your strategy on Horizon Cloud">
    ```python
    import horizon as hz

    cloud = hz.HorizonCloud()
    strat = cloud.create_strategy(name="BTC MM Alpha", code=open("strategy.py").read())
    cloud.deploy(strat["id"], credential_id="cred-id", mode="live")
    ```
  </Step>
  <Step title="Publish to the marketplace">
    ```python
    listing = hz.marketplace.publish(
        strat["id"],
        mode="signal",
        price=49.99,                    # $49.99/month
        description="High-Sharpe BTC market making strategy",
        tags=["btc", "market-making", "polymarket"],
        exchange="polymarket",
    )
    print(listing)  # Listing('BTC MM Alpha' [signal] $49.99, id=abc12345...)
    ```

    Subscribers will receive your strategy's order signals **without ever seeing your code**.
  </Step>
</Steps>

### Subscribing

```python
import horizon as hz

# Subscribe
sub = hz.marketplace.subscribe(
    "listing-id",
    size_scale=0.5,        # Half the author's position sizes
    max_position=500.0,    # $500 max per market
)
print(sub)  # Subscription('BTC MM Alpha' [active], id=xyz...)

# Follow signals in real-time (blocking loop)
hz.marketplace.follow(
    sub.id,
    exchange="paper",      # Start with paper trading
    poll_interval=5.0,
    dry_run=True,          # Preview signals first
)
```

### Pipeline Mode

Use `signal_follower()` inside `hz.run()` for integration with your own pipeline:

```python
import horizon as hz

hz.run(
    name="signal-follower",
    markets=["btc-100k"],
    pipeline=[
        hz.signal_follower(
            subscription_id="sub-abc",
            size_scale=0.5,
            max_position=500.0,
        ),
    ],
    interval=5.0,
)
```

### What Subscribers See

Signals contain **only order data**, no source code, parameters, or feed data:

```python
Signal(BUY yes 50.00@0.6200 on will-btc-hit-100k)
# Fields: market_id, side, order_side, price, size, timestamp
```

<Tip>
The subscriber's local Engine runs their own risk pipeline, so they retain full risk control over position sizing, drawdown limits, and order filtering.
</Tip>

## Unlisted Listings

Publish strategies as **unlisted** to restrict access. Unlisted listings don't appear in browse or leaderboard. Only people with the invite code can view, subscribe, or purchase.

<Steps>
  <Step title="Publish as unlisted">
    ```python
    import horizon as hz

    listing = hz.marketplace.publish(
        "strategy-id",
        mode="signal",
        price=99.99,
        visibility="unlisted",
    )
    print(listing.invite_code)  # "a1b2c3d4e5f6g7h8" - share this with your group
    ```
  </Step>
  <Step title="Share the invite code">
    Recipients use the invite code to access the listing:

    ```python
    # Subscribe with invite code
    sub = hz.marketplace.subscribe("listing-id", invite_code="a1b2c3d4e5f6g7h8")

    # Purchase with invite code
    purchase = hz.marketplace.purchase("listing-id", invite_code="a1b2c3d4e5f6g7h8")

    # View listing details
    listing = hz.marketplace.get_listing("listing-id", invite_code="a1b2c3d4e5f6g7h8")
    ```
  </Step>
</Steps>

You can switch a listing between public and unlisted at any time:

```python
hz.marketplace.update_listing("listing-id", visibility="unlisted")
hz.marketplace.update_listing("listing-id", visibility="public")
```

## Package Mode (Direct Sale)

### Publishing

```python
import horizon as hz

listing = hz.marketplace.publish(
    "strategy-id",
    mode="package",
    price=299.99,                    # One-time price
    description="Complete BTC MM strategy with full source code",
    tags=["btc", "market-making"],
    max_sales=1,                     # Exclusive: only 1 buyer
)
```

Set `max_sales=1` for exclusive sales, or leave as `None` for unlimited.

### Purchasing

<Steps>
  <Step title="Purchase (opens Stripe checkout)">
    ```python
    import horizon as hz

    purchase = hz.marketplace.purchase("listing-id")
    print(purchase.checkout_url)  # Complete payment in browser
    ```
  </Step>
  <Step title="Download encrypted package">
    ```python
    hz.marketplace.download(purchase.id)
    ```
  </Step>
  <Step title="Activate with license key">
    ```python
    result = hz.marketplace.activate(
        purchase.id,
        license_key=purchase.license_key,
    )
    print(result["code_path"])  # ~/.horizon/marketplace/btc_mm/strategy.py
    ```
  </Step>
</Steps>

## Managing Listings

```python
import horizon as hz

# View your listings
my = hz.marketplace.my_listings()

# Update pricing, description, or tags
hz.marketplace.update_listing("listing-id", price=39.99)
hz.marketplace.update_listing("listing-id", description="Updated description")
hz.marketplace.update_listing("listing-id", tags=["btc", "momentum"])

# Pause: stops new subscriptions/purchases, existing subscribers keep access
hz.marketplace.pause_listing("listing-id")

# Resume: re-enables the listing for new buyers
hz.marketplace.resume_listing("listing-id")

# Delist: permanently removes from marketplace, cancels all active subscriptions
hz.marketplace.delist("listing-id")
```

| Action | Visible in Browse | New Buyers | Existing Subscribers | Reversible |
|--------|:-:|:-:|:-:|:-:|
| **Update** | Yes | Yes | Unaffected | Yes |
| **Pause** | No | Blocked | Keep access | Yes (resume) |
| **Resume** | Yes | Yes | Unaffected | Yes |
| **Delist** | No | Blocked | Canceled | No |

<Warning>
**Delist** is permanent and cannot be undone. All active subscriptions will be canceled. Use **Pause** if you want to temporarily hide a listing.
</Warning>

**Auto-delist**: Package listings with `max_sales` are automatically delisted when the purchase limit is reached.

## Earnings

```python
import horizon as hz

earnings = hz.marketplace.listing_earnings("listing-id")
print(f"Total revenue: ${earnings.total_revenue:.2f}")
print(f"Your share (90%): ${earnings.author_share:.2f}")
print(f"Platform fee (10%): ${earnings.platform_fee:.2f}")
print(f"Subscribers: {earnings.total_subscribers}")
```

## Verification Badges

Two trust layers help buyers evaluate listings and authors.

<CardGroup cols={2}>
  <Card title="Verified Performance" icon="chart-line">
    Strategy-level badge. Metrics computed by the platform from real cloud deployment data. Cannot be faked.
  </Card>
  <Card title="Verified Trader" icon="user-check">
    Author-level badge. Proves the author has a real trading track record via on-chain or exchange API verification.
  </Card>
</CardGroup>

### Verified Performance

Computed from your strategy's live cloud deployment. Requires **14+ days deployed** with **10+ trades**.

```python
import horizon as hz

# Request badge (must be listing owner)
badge = hz.marketplace.verify_performance("listing-id")
print(badge)
# VerifiedPerformance(verified=True, sharpe=1.42, total_pnl=523.40,
#   win_rate=0.58, max_drawdown=0.12, total_trades=247,
#   measurement_period_days=28)

# Check badges on any listing
badges = hz.marketplace.listing_badges("listing-id")
```

<Tip>
Verified Performance badges are recomputed from real `metrics_snapshots` data. The platform measures Sharpe, PnL, win rate, and drawdown from actual fills, not self-reported numbers.
</Tip>

### Verified Trader

Proves the author is a real, profitable trader. Works via on-chain wallet verification (Polymarket) or exchange API (Kalshi).

<Steps>
  <Step title="Start verification">
    ```python
    import horizon as hz

    # Polymarket: on-chain verification via Polygon
    req = hz.marketplace.verify_trader(
        "polymarket",
        wallet_address="0x1234...abcd",
    )
    print(req.status)  # "pending"

    # Kalshi: API verification via stored credentials
    req = hz.marketplace.verify_trader(
        "kalshi",
        credential_id="cred-456",
    )
    ```
  </Step>
  <Step title="Check status (async)">
    ```python
    requests = hz.marketplace.verification_status()
    for r in requests:
        print(f"{r.exchange}: {r.status}")
    ```
  </Step>
  <Step title="View author badges">
    ```python
    author = hz.marketplace.author_badges("author-id")
    print(f"Verified: {author.verified}")
    print(f"Exchanges: {author.exchanges}")
    print(f"Total PnL: ${author.aggregate_pnl:.2f}")
    print(f"Active: {author.time_active_days} days")
    ```
  </Step>
</Steps>

### Filtering by Verified

```python
# Browse only verified listings
listings = hz.marketplace.browse(verified_only=True)
```

Badges expire after **90 days** and require re-verification to stay active.

## Anti-Resale Protection

The platform automatically protects strategy authors from resale:

| Layer | How It Works |
|-------|-------------|
| **AST fingerprinting** | Every uploaded strategy is fingerprinted (normalized AST hash, API call patterns, structural graph). |
| **Purchase-aware comparison** | When a user publishes, their upload is compared against all strategies they've previously purchased. High similarity is blocked. |
| **LLM review** | Borderline cases (50-85% similarity with minor modifications) are flagged for semantic comparison. |
| **Timing detection** | Publishing shortly after purchasing a similar strategy lowers the flagging threshold. |

<Tip>
Signal-mode strategies are inherently safe. Code never leaves the Cloud Worker.
</Tip>

## MCP Tools

All marketplace operations are available as [MCP tools](/integrations/mcp-server):

| Tool | Description |
|------|-------------|
| `marketplace_browse` | Search and filter listings |
| `marketplace_get_listing` | Get listing details |
| `marketplace_leaderboard` | Top strategies by performance |
| `marketplace_publish` | Publish a strategy |
| `marketplace_my_listings` | Your published listings |
| `marketplace_listing_earnings` | Earnings breakdown |
| `marketplace_subscribe` | Subscribe to signal-mode listing |
| `marketplace_unsubscribe` | Cancel a subscription |
| `marketplace_my_subscriptions` | Your subscriptions |
| `marketplace_signals` | Fetch recent signals |
| `marketplace_purchase` | Purchase a package listing |
| `marketplace_my_purchases` | Your purchases |
| `marketplace_connect_payments` | Start Stripe Connect onboarding |
| `marketplace_payment_status` | Check payment connection status |
| `marketplace_verify_performance` | Request Verified Performance badge |
| `marketplace_listing_badges` | Get badge details for a listing |
| `marketplace_verify_trader` | Start Verified Trader verification |
| `marketplace_verification_status` | Check verification request status |

## API Reference

### Marketplace

| Method | Description |
|--------|-------------|
| `browse(query, tags, mode, exchange, sort_by, limit)` | Search listings |
| `get_listing(listing_id, invite_code)` | Get listing details |
| `leaderboard(timeframe, limit)` | Top performers |
| `listing_performance(listing_id)` | Detailed equity curve |
| `publish(strategy_id, mode, price, visibility, ...)` | Publish a listing |
| `update_listing(listing_id, **kwargs)` | Update metadata |
| `pause_listing(listing_id)` | Pause listing |
| `resume_listing(listing_id)` | Resume listing |
| `delist(listing_id)` | Permanently remove |
| `my_listings()` | Your listings |
| `listing_earnings(listing_id)` | Revenue breakdown |
| `connect_payments()` | Stripe Connect onboarding |
| `payment_status()` | Check payment status |
| `subscribe(listing_id, size_scale, max_position, invite_code)` | Subscribe to signals |
| `unsubscribe(subscription_id)` | Cancel subscription |
| `my_subscriptions()` | Your subscriptions |
| `signals(subscription_id, since, limit)` | Fetch signals |
| `follow(subscription_id, ...)` | Execute signals (blocking) |
| `purchase(listing_id, invite_code)` | Buy a package listing |
| `my_purchases()` | Your purchases |
| `download(purchase_id)` | Download encrypted package |
| `activate(purchase_id, license_key)` | Decrypt with license key |
| `verify_license(purchase_id)` | Check license validity |
| `verify_performance(listing_id)` | Request Verified Performance badge |
| `listing_badges(listing_id)` | Get badge details for a listing |
| `verify_trader(exchange, wallet_address, credential_id)` | Start Verified Trader verification |
| `verification_status()` | Check verification request status |
| `author_badges(author_id)` | Get author's Verified Trader badge |

### signal_follower()

Pipeline function for use with `hz.run()`:

```python
hz.signal_follower(
    subscription_id: str,
    size_scale: float = 1.0,
    max_position: float = 1000.0,
    signal_ttl: float = 60.0,
    dry_run: bool = False,
) -> Callable
```
