Skip to main content

The Problem with LLM Trading

Most AI trading systems face a fundamental problem: context acquisition. When an LLM needs to make trading decisions, it typically:
  1. Searches the web for information
  2. Parses unstructured text
  3. Extracts entities and relationships
  4. Hopes it didn’t hallucinate
This is slow, unreliable, and error-prone.

Market Motion Solution

One API call gives your AI agent everything it needs—structured, typed, attributed data.
// Instead of: "Search web for Patrick Mahomes injury news"
// Do this:
const entity = await fetch('/api/entities/patrick-mahomes');

// Directly access structured data
const injuryStatus = entity.attributes.injury_status; // "questionable"
const source = entity.attributes.injury_status_source; // "ESPN"
const affectedMarkets = entity.marketExposures; // Array of markets

Architecture Pattern

1

Entity Discovery

Use search or categories to find relevant entities
2

Context Retrieval

Fetch entity details with relationships and market exposures
3

Signal Detection

Monitor attribute changes that signal trading opportunities
4

Market Mapping

Identify which markets are affected by entity changes
5

Trade Execution

Execute trades on Polymarket/Kalshi directly

Example: Sports Betting Agent

import requests

BASE_URL = "https://api.marketmotion.xyz/api"

class SportsAgent:
    def __init__(self, api_key=None):
        self.headers = {"X-API-Key": api_key} if api_key else {}

    def check_injury_opportunities(self, team_slug):
        """Find betting opportunities from injury updates."""

        # Get team entity
        team = requests.get(
            f"{BASE_URL}/entities/{team_slug}",
            headers=self.headers
        ).json()["entity"]

        # Get all players on the team
        players = [
            r["entity"] for r in team.get("relationships", [])
            if r["role"] == "has_player"
        ]

        opportunities = []

        for player_ref in players:
            # Get full player details
            player = requests.get(
                f"{BASE_URL}/entities/{player_ref['slug']}",
                headers=self.headers
            ).json()["entity"]

            injury_status = player.get("attributes", {}).get("injury_status")

            if injury_status in ["questionable", "out"]:
                # This player's status may affect markets
                opportunities.append({
                    "player": player["displayName"],
                    "status": injury_status,
                    "markets": player.get("marketExposures", []),
                    "source": player["attributes"].get("injury_status_source")
                })

        return opportunities

# Usage
agent = SportsAgent(api_key="your_key")
opps = agent.check_injury_opportunities("kansas-city-chiefs")

for opp in opps:
    print(f"{opp['player']} is {opp['status']}")
    print(f"  Source: {opp['source']}")
    print(f"  Affected markets: {len(opp['markets'])}")

Example: Political Event Agent

class PoliticsAgent:
    def monitor_approval_ratings(self):
        """Monitor politicians for approval rating changes."""

        # Get all politicians
        response = requests.get(
            f"{BASE_URL}/entities",
            params={"category": "politics", "type": "person", "limit": 100},
            headers=self.headers
        ).json()

        signals = []

        for pol in response["data"]["entities"]:
            attrs = pol.get("attributes", {})
            approval = attrs.get("approval_rating")

            if approval and approval < 40:
                # Low approval - check for election markets
                full_entity = requests.get(
                    f"{BASE_URL}/entities/{pol['slug']}",
                    headers=self.headers
                ).json()["entity"]

                election_markets = [
                    m for m in full_entity.get("marketExposures", [])
                    if "election" in m["market"]["title"].lower()
                ]

                if election_markets:
                    signals.append({
                        "politician": pol["displayName"],
                        "approval": approval,
                        "markets": election_markets
                    })

        return signals

Prompt Engineering with Entity Context

When using LLMs for trading decisions, inject entity context:
def build_trading_prompt(entity_slug, question):
    """Build an LLM prompt with full entity context."""

    # Fetch entity
    entity = requests.get(f"{BASE_URL}/entities/{entity_slug}").json()["entity"]

    # Fetch relationship graph
    graph = requests.get(
        f"{BASE_URL}/entities/{entity_slug}/graph",
        params={"depth": 2}
    ).json()["graph"]

    # Build context
    context = f"""
Entity: {entity['displayName']} ({entity['entityType']})
Category: {entity['category']}/{entity.get('subcategory', 'N/A')}

Attributes:
{json.dumps(entity.get('attributes', {}), indent=2)}

Relationships:
{chr(10).join([f"- {r['role']}: {r['entity']['displayName']}" for r in entity.get('relationships', [])])}

Connected Markets ({len(entity.get('marketExposures', []))} total):
{chr(10).join([f"- {m['market']['title']} ({m['market']['venue']})" for m in entity.get('marketExposures', [])[:5]])}

Relationship Graph: {len(graph['nodes'])} nodes, {len(graph['edges'])} edges
"""

    prompt = f"""You are a trading analyst. Given the following entity data, {question}

{context}

Provide your analysis:"""

    return prompt

Best Practices

Entity attributes don’t change every second. Cache for 5-15 minutes to reduce API calls and latency.
Depth 1 is usually enough. Depth 2-3 for complex relationship analysis. More depth = more data to process.
Every attribute includes a source. Use this to weight confidence in your trading decisions.
Use Market Motion for context and discovery. Execute trades directly on venue APIs for speed.

LLM Context File

For AI systems that need comprehensive API documentation, use our machine-readable context file:
https://marketmotion.xyz/llms.txt
This contains all endpoints, schemas, and examples in a format optimized for LLM consumption.