# Polymarket + Kalshi Arbitrage Opportunity Radar (`nexascout/prediction-market-opportunity-risk-radar`) Actor

Find equivalent Polymarket and Kalshi contracts, reject false arbitrage, and calculate fee- and depth-aware executable cross-market opportunities.

- **URL**: https://apify.com/nexascout/prediction-market-opportunity-risk-radar.md
- **Developed by:** [NexaScout](https://apify.com/nexascout) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Polymarket + Kalshi Arbitrage Opportunity Radar

Find equivalent contracts across **Polymarket** and **Kalshi**, reject false arbitrage before it reaches the economics layer, and estimate whether a cross-venue trade is actually executable after order-book depth and fees.

The Actor is designed for research, monitoring, agent workflows, and automated opportunity triage. It does **not** assume that similar titles represent the same bet.

### What you get

Each validated row can include:

- canonical cross-platform event identity
- contract type and scope
- match confidence
- resolution-risk score and reasons
- direct Polymarket and Kalshi market data
- executable contracts from live order-book depth
- average and worst fill prices
- estimated platform fees
- settlement payout
- estimated net profit
- estimated net edge
- `ACTIONABLE`, `WATCH`, or `REJECT`
- `NEW`, `CHANGED`, or `UNCHANGED` for monitoring runs

A separate run summary reports discovery counts, canonical coverage, shared event keys, semantic-gate counts, source diagnostics, and signal totals.

### Safety-first matching pipeline

```text
Polymarket + Kalshi discovery
          ↓
platform normalization
          ↓
canonical event fingerprint
          ↓
contract type + contract scope
          ↓
resolution-equivalence gate
          ↓
ONLY validated pairs
          ↓
live order-book depth
          ↓
fee-aware execution economics
          ↓
ACTIONABLE / WATCH / REJECT
```

The Actor intentionally performs **semantic validation before arbitrage math**.

### Supported matching

#### Sports

Sports matching normalizes league, teams, scheduled date, market type, outcome side, and contract scope.

Cross-venue execution economics are precision-first. Only:

> **FULL\_GAME moneyline / winner ↔ FULL\_GAME moneyline / winner**

can pass the execution gate.

The Actor rejects derivatives such as:

- first-half or quarter moneylines
- spreads
- totals
- inning markets
- exact winning margins
- longest field goal
- scoring props
- safety / overtime props
- player props

even when they share the same underlying game.

#### Macro

Canonical matching supports market families such as:

- Fed meeting decisions
- CPI
- unemployment
- GDP
- payrolls

Metric, period, comparator, threshold, and contract semantics are checked before economics.

#### Crypto and weather

The Actor normalizes asset/location, metric, target date or period, comparator, and threshold before pairing contracts. Unsupported or non-equivalent structures are rejected conservatively.

### Signals

#### `ACTIONABLE`

A research signal that passes the configured semantic, resolution-risk, fee, depth, and net-edge gates.

It is **not** an execution guarantee.

#### `WATCH`

The pair is semantically valid, but current execution economics or another configured threshold is not strong enough for `ACTIONABLE`.

#### `REJECT`

The pair fails a semantic, contract-scope, resolution, or hard safety gate. Rejected rows are omitted by default and can be included for audits.

### Quick start — NFL opportunity scan

```json
{
  "searchQueries": ["NFL"],
  "verticals": ["SPORTS"],
  "maxMarketsPerPlatform": 1000,
  "maxMatches": 10,
  "assumedTradeSize": 25,
  "minNetEdgePct": 1,
  "minExecutableContracts": 5,
  "candidateMatchConfidence": 0.72,
  "actionableMatchConfidence": 0.9,
  "maxResolutionRiskScore": 45,
  "polymarketFeeMode": "AUTO",
  "requireKnownFeesForActionable": true,
  "includeRejected": false,
  "compareWithPreviousRun": false
}
```

### Contract-equivalence audit

To inspect why same-event contracts were rejected:

```json
{
  "searchQueries": ["Yankees"],
  "verticals": ["SPORTS"],
  "maxMatches": 20,
  "includeRejected": true,
  "compareWithPreviousRun": false
}
```

Use the **Semantic & resolution risk** dataset view to inspect market type, scope, match confidence, and risk reasons.

### Monitoring

Enable:

```json
{
  "compareWithPreviousRun": true,
  "historyKey": "my-strategy-watch"
}
```

Runs with the same history key can label matched opportunities as `NEW`, `CHANGED`, or `UNCHANGED`.

This is useful for Apify schedules, webhooks, agents, and recurring market scans.

### Fee-aware economics

The execution layer walks multiple order-book levels and estimates actual fillability rather than assuming unlimited top-of-book size.

For each strategy it can report:

- executable contracts
- average ask per leg
- worst ask per leg
- gross cost
- estimated fees
- total cost
- settlement payout
- estimated net profit
- estimated net edge

`polymarketFeeMode=AUTO` uses the supported category fee treatment when it can be established. Unknown fee treatment remains conservative when `requireKnownFeesForActionable=true`.

### Dataset views

The default dataset includes three useful views:

- **Opportunity overview** — signals, markets, match/risk scores, edge, and executable size
- **Execution economics** — strategy, cost, fees, payout, profit, and net edge
- **Semantic & resolution risk** — event identity, contract types/scopes, confidence, and rejection reasons

### Cost controls

The Actor uses pay-per-event Store pricing.

Current published pricing is intentionally simple:

- Actor start event
- per-result dataset event

`maxMatches` is the main billable-output safety limit. Lower it for exploratory runs.

### Agent and automation use

The Actor is designed for structured API/agent workflows:

- JSON input
- structured dataset rows
- deterministic signal fields
- run diagnostics in `OUTPUT`
- persistent monitoring keys
- limited Actor permissions
- no Standby dependency

### Important limitations

- Cross-venue rules can differ even when event identity is exact.
- Cancellation/postponement rules can create material settlement risk.
- Order books can change between data capture and execution.
- Platform access, account eligibility, balances, and order fills are external to this Actor.
- Public platform schemas and fee schedules can change and require maintenance.
- A result labeled `ACTIONABLE` is a research classification, **not financial advice or an execution guarantee**.

### Version

Store-ready source package: **2.8.1**

Validated matching engine: **2.8.0 / contract-semantics-v7**

# Changelog

This Actor's version history is a separate document: https://apify.com/nexascout/prediction-market-opportunity-risk-radar/changelog.md

# Actor input Schema

## `searchQueries` (type: `array`):

Optional focused topics such as NFL, Yankees, Fed, CPI, unemployment, or Bitcoin. Team and league aliases are normalized before matching.

## `verticals` (type: `array`):

Limit discovery to selected market verticals. Sports economics are precision-first and only full-game winner/moneyline contracts can pass the execution gate.

## `maxMarketsPerPlatform` (type: `integer`):

Maximum open markets loaded from each platform before local query filtering and canonical grouping.

## `maxMatches` (type: `integer`):

Maximum dataset rows returned and billed. Lower this value for cheaper exploratory runs.

## `assumedTradeSize` (type: `number`):

Maximum contracts used for depth-aware executable economics.

## `minNetEdgePct` (type: `number`):

Minimum estimated return after known fees for ACTIONABLE.

## `minExecutableContracts` (type: `number`):

Minimum contracts that must be fillable from both books for ACTIONABLE.

## `candidateMatchConfidence` (type: `number`):

Minimum semantic match confidence for a pair to reach the resolution-equivalence gate.

## `actionableMatchConfidence` (type: `number`):

A pair below this confidence can never be ACTIONABLE.

## `maxResolutionRiskScore` (type: `integer`):

Pairs above this 0-100 risk score cannot be ACTIONABLE.

## `maxEventDateDifferenceHours` (type: `integer`):

Maximum allowed event-time difference for time-specific markets. Sports event dates are matched more strictly when both dates are known.

## `kalshiFeeCoefficient` (type: `number`):

Default Kalshi event-contract taker fee coefficient used when no market-specific exception is detected.

## `polymarketFeeMode` (type: `string`):

AUTO uses the current Polymarket category taker-fee curve when the normalized category/vertical is known, treats explicitly fee-free markets as zero-fee, and leaves unfamiliar fee categories unknown. OVERRIDE\_BPS and ASSUME\_ZERO remain explicit research overrides.

## `polymarketFeeBps` (type: `number`):

Used only when Polymarket fee handling is OVERRIDE\_BPS.

## `requireKnownFeesForActionable` (type: `boolean`):

Recommended. If enabled, a fee-enabled market whose applicable fee category cannot be established is WATCH/REJECT rather than ACTIONABLE.

## `includeRejected` (type: `boolean`):

Include pairs rejected by contract-scope, event, threshold, or resolution checks. Useful for audits; leave disabled for normal opportunity scans.

## `compareWithPreviousRun` (type: `boolean`):

Persist prior matched opportunities and label rows NEW, CHANGED, or UNCHANGED. Enable for scheduled monitoring.

## `historyKey` (type: `string`):

Stable monitoring key. Runs using the same key are compared with one another when Track changes is enabled.

## `maxConcurrency` (type: `integer`):

Concurrent quote requests after semantic and resolution gates pass.

## `sourceRetries` (type: `integer`):

Retries for public market-data endpoints, including HTTP 429 backoff and Kalshi host fallback.

## Actor input object example

```json
{
  "searchQueries": [],
  "verticals": [
    "SPORTS",
    "MACRO",
    "CRYPTO",
    "WEATHER",
    "POLITICS",
    "GENERAL"
  ],
  "maxMarketsPerPlatform": 1000,
  "maxMatches": 10,
  "assumedTradeSize": 25,
  "minNetEdgePct": 1,
  "minExecutableContracts": 5,
  "candidateMatchConfidence": 0.72,
  "actionableMatchConfidence": 0.9,
  "maxResolutionRiskScore": 25,
  "maxEventDateDifferenceHours": 12,
  "kalshiFeeCoefficient": 0.07,
  "polymarketFeeMode": "AUTO",
  "polymarketFeeBps": 0,
  "requireKnownFeesForActionable": true,
  "includeRejected": false,
  "compareWithPreviousRun": false,
  "historyKey": "default",
  "maxConcurrency": 6,
  "sourceRetries": 4
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `overview` (type: `string`):

No description

## `economics` (type: `string`):

No description

## `riskAudit` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nexascout/prediction-market-opportunity-risk-radar").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("nexascout/prediction-market-opportunity-risk-radar").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call nexascout/prediction-market-opportunity-risk-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexascout/prediction-market-opportunity-risk-radar"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/fLOb1G9PAD9vFDIah/builds/EDPWBim9n36bPMaoF/openapi.json
