# How CloddsBot Performs Cross-Platform Arbitrage Detection Using Semantic Matching

> Discover how CloddsBot detects cross-platform arbitrage using semantic matching. Learn to encode market titles, match events with vector embeddings, and calculate price spreads.

- Repository: [AL/CloddsBot](https://github.com/alsk1992/CloddsBot)
- Tags: how-to-guide
- Published: 2026-09-14

---

**CloddsBot identifies arbitrage opportunities across prediction market platforms by encoding market titles into vector embeddings and computing cosine similarity to match identical underlying events, then verifies these semantic matches before calculating cross-venue price spreads.**

Cross-platform arbitrage detection using semantic matching is the core mechanism that enables the `alsk1992/CloddsBot` system to find identical prediction markets listed on different venues like Polymarket, Kalshi, and Manifold. The TypeScript implementation leverages vector embeddings to overcome platform-specific naming inconsistencies and surface genuine arbitrage edges. This article breaks down the exact source code implementation found in the repository's opportunity matching pipeline.

## Semantic Matching Architecture

### The Opportunity Matcher Core

The semantic matching logic resides in [`src/opportunity/matching.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/matching.ts), where the `matchMarkets` function implements the primary detection algorithm. According to the alskk1992/CloddsBot source code, this component first attempts **semantic matching** using vector embeddings when the `semanticEnabled` flag is active, with a default similarity threshold of **0.85** (lines 2-70).

When matching markets, the system:
1. Generates embeddings for the target market title using the embeddings service
2. Queries the vector database for the top-K nearest neighbors (controlled by `semanticSearchTopK`)
3. Computes cosine similarity between vectors
4. Verifies matches that exceed the threshold using secondary checks (slug comparison or exact outcome mapping)

The matcher returns a verified match object with `method: 'semantic'` when successful, allowing downstream components to proceed with price analysis.

### The Opportunity Indexer

The [`src/opportunity/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/index.ts) file orchestrates the full arbitrage scanning workflow (lines 79-85). This component:
- Fetches live market data from all enabled platform connectors
- Passes the `semanticMatching` configuration flag to the matcher
- Supplies the `semanticSearchTopK` parameter (default 5) to limit vector search scope
- Feeds matched pairs to the arbitrage planner for edge calculation

According to the source code, the indexer only enables semantic matching automatically when embeddings are available in the runtime environment.

### Embeddings Service Provider

Located at [`src/embeddings/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/embeddings/index.ts) (lines 2-10), the embeddings service provides the vectorization backend for the entire matching system. The implementation supports multiple providers through a plugin architecture:

- **OpenAI** API for high-quality text embeddings
- **Voyage** AI for specialized semantic search
- **Local models** via [`transformers.js`](https://github.com/alsk1992/CloddsBot/blob/main/transformers.js) for offline operation

The service caches generated vectors to ensure repeated arbitrage scans remain performant, reusing embeddings for market titles that have already been processed.

### Venue-Arbitrage Planner

Once the Opportunity Matcher validates a semantic pair, [`src/trading/venue-arbitrage-scanner.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/venue-arbitrage-scanner.ts) (lines 8-20) constructs the executable arbitrage plan. This component is venue-agnostic—it receives the matched market IDs and fetches current price quotes from each platform to calculate the percentage edge. The planner determines optimal order sizing and routing (which venue to buy from, which to sell to) based on the verified semantic match.

## Step-by-Step Arbitrage Detection Flow

The complete cross-platform arbitrage detection using semantic matching follows this implementation path:

1. **Market Data Aggregation** – Connectors pull live order books from enabled platforms (Polymarket, Kalshi, Manifold, etc.)

2. **Outcome Normalization** – [`src/opportunity/outcomes.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/outcomes.ts) converts platform-specific representations (yes/no, up/down, true/false) into a canonical format

3. **Vector Generation** – Each market title/description is sent to the embeddings service (`memory.semanticSearch`) to produce a dense vector representation

4. **Similarity Search** – The matcher queries the vector database for the top-K nearest neighbors based on `semanticSearchTopK` (default 5) and calculates cosine similarity scores

5. **Threshold Verification** – Matches exceeding the 0.85 similarity threshold undergo additional verification to confirm they refer to the same underlying event (comparing slugs or exact outcome mappings)

6. **Edge Calculation** – For verified pairs, the bot fetches best bid/ask prices on each venue, computes the percentage spread, and filters by the user-defined `minEdge` parameter

7. **Plan Execution** – The venue-arbitrage planner creates a concrete order-routing plan and hands it to the execution engine

## Configuration and Usage

### Enabling Semantic Matching

According to [`src/utils/config.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/config.ts), the system exposes several configuration parameters that control cross-platform arbitrage detection:

```json
{
  "opportunityFinder": {
    "semanticMatching": true,
    "semanticSearchTopK": 10,
    "minEdge": 1.5
  },
  "memory": {
    "auto": {
      "semanticSearchTopK": 10
    }
  }
}

```

Setting `semanticMatching: true` activates the embedding-based matcher. The `semanticSearchTopK` parameter controls how many candidate markets are examined per query, balancing recall against latency.

### Running the Arbitrage Scanner

The following TypeScript example demonstrates how to invoke the opportunity finder programmatically, following the same path as the `/arb` chat command:

```typescript
import { opportunityFinder } from './opportunity';
import { Config } from './utils/config';

// Example config – enable semantic matching and limit to 5 nearest vectors
const cfg: Config = {
  opportunityFinder: {
    semanticMatching: true,
    semanticSearchTopK: 5,
    minEdge: 2,               // % edge required to report
  },
};

async function runScan() {
  // Scan all enabled venues and return any arbitrage pairs
  const results = await opportunityFinder.scan(cfg);
  console.log('Arbitrage opportunities:', results);
}

runScan().catch(console.error);

```

This script initializes the semantic matching pipeline and returns any verified arbitrage opportunities found across configured platforms.

### Direct Market Matching

For testing or custom integrations, you can invoke the semantic matcher directly without running the full scanner:

```typescript
import { matchMarkets } from './opportunity/matching';
import { getEmbeddings } from './embeddings';

// Suppose we have two market objects from different platforms
const marketA = { title: 'Will Bitcoin break $30k by 2025?', platform: 'polymarket', ... };
const marketB = { title: 'Bitcoin price > $30,000 on 2025‑12‑31?', platform: 'kalshi', ... };

async function demo() {
  const embeddings = await getEmbeddings(); // initialise provider
  const match = await matchMarkets(marketA, [marketB], { embeddings, semanticEnabled: true });
  if (match) {
    console.log('Semantic match found with score', match.score);
  } else {
    console.log('No semantic match');
  }
}
demo();

```

The `matchMarkets` function handles vector lookup, similarity scoring, and verification in a single call, returning the match confidence score when successful.

## Summary

- **Vector Embeddings Bridge Platforms**: CloddsBot uses dense vector representations of market titles in [`src/opportunity/matching.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/matching.ts) to overcome semantic differences between platform naming conventions.

- **Configurable Similarity Thresholds**: The default 0.85 cosine similarity threshold and top-K search parameters (default 5) in [`src/opportunity/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/index.ts) balance precision with computational efficiency.

- **Multi-Provider Embedding Support**: The [`src/embeddings/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/embeddings/index.ts) architecture supports OpenAI, Voyage, and local [`transformers.js`](https://github.com/alsk1992/CloddsBot/blob/main/transformers.js) models, with built-in caching for performance.

- **Verification Prevents False Positives**: Even high-similarity matches undergo secondary verification (slug or outcome comparison) before being passed to [`src/trading/venue-arbitrage-scanner.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/venue-arbitrage-scanner.ts) for price analysis.

- **Unified Command Interface**: The `/arb` skill in [`src/skills/bundled/arbitrage/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/bundled/arbitrage/index.ts) exposes the entire pipeline through a single chat command, using the same configuration structure as the programmatic API.

## Frequently Asked Questions

### How does CloddsBot handle different naming conventions across platforms?

CloddsBot converts market titles into vector embeddings using the service in [`src/embeddings/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/embeddings/index.ts), which captures semantic meaning rather than relying on exact string matches. This allows the system to recognize that "Will Bitcoin break $30k by 2025?" and "Bitcoin price > $30,000 on 2025‑12‑31?" refer to the same underlying event despite different phrasing, formatting, and date representations.

### What similarity threshold indicates a valid semantic match?

According to the source code in [`src/opportunity/matching.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/matching.ts), the default **cosine similarity threshold is 0.85**. Matches exceeding this value are flagged as potential semantic equivalents, though they still undergo secondary verification (comparing market slugs or outcome mappings) before being accepted as valid arbitrage pairs.

### Can the arbitrage scanner operate without semantic embeddings?

Yes. The `semanticMatching` configuration flag in [`src/opportunity/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/index.ts) allows the system to fall back to plain-text or slug-based comparison methods when embeddings are unavailable or disabled. However, semantic matching significantly improves recall for cross-platform arbitrage detection by identifying paraphrased or differently formatted market titles that exact-match algorithms would miss.

### How does the system prevent false positive arbitrage signals?

Even when vector similarity exceeds the 0.85 threshold, the matcher in [`src/opportunity/matching.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/opportunity/matching.ts) performs additional verification around line 70 to confirm the markets truly reference the same event. This includes comparing platform-specific identifiers (slugs) and verifying that outcome mappings align correctly. Only after this verification step does the venue-arbitrage scanner calculate price spreads and generate trading plans.