Overview Architecture ClawBox Setup Data Sources Agents Intelligence Stack Deploy
// OVERVIEW

OrganizedMarket

Hard price data from TastyTrade. Prediction market odds from Polymarket and Kalshi. Sentiment from Twitter/X and financial news — all wired into a correlation engine running inside ClawBox's isolated Linux VM, orchestrated through OpenClaw. Surfaces arbitrage-adjacent signals across venues in real time.

ClawBox OpenClaw :18789 TastyTrade DXLink Polymarket CLOB API Kalshi REST Twitter/X v2 Claude Sonnet CF Pages
6
Agents
3
Data Sources
RT
Streaming
Signal Loop

The Core Idea

Prediction markets price real-world outcomes. Financial markets price risk. When they diverge — a Polymarket contract implying a Fed cut with probability X while /ZQ options price something different — there's signal. OrganizedMarket finds that gap continuously.

One source of truth
Cross-venue price divergence. Agent conclusions are derived from hard data — DXLink quotes, CLOB order books, contract resolution odds.
One metric
Signal confidence 0.0–1.0. High (>0.75) fires an alert immediately. Medium (0.45–0.75) queues for pattern confirmation. Low is logged to the flywheel.
One directive
Find correlation before causation. Twitter sentiment and news cycle events are leading indicators. Hard price data is ground truth. Never invert that hierarchy.
Human review gate
OrganizedMarket surfaces signals — it does not execute trades. All alerts include a confidence score, data provenance, and a plain-English summary before any action.

Explore the Guide

// ARCHITECTURE

System Architecture

OrganizedMarket runs entirely inside ClawBox — a Tauri-wrapped macOS app that spins up an isolated Ubuntu 24.04 VM via Lima. OpenClaw runs inside that VM as the agent gateway. Your Mac stays clean; only explicitly uploaded files are shared with the VM.

               ORGANIZEDMARKET — SYSTEM DIAGRAM

┌──────────────────────────────────────────────────────────────────┐
│  CLAWBOX (Tauri + React)                                         │
│  Native macOS UI · one-click VM lifecycle                        │
├──────────────────────────────────────────────────────────────────┤
│  LIMA VM MANAGER                                                 │
│  Ubuntu 24.04 · isolated from host Mac                          │
├──────────────────────────────────────────────────────────────────┤
│  OPENCLAW GATEWAY  :18789                                        │
│                                                                  │
│  ┌────────────────┐  ┌────────────────┐  ┌──────────────────┐  │
│  │ agent-signal   │  │ agent-poly     │  │ agent-kalshi     │  │
│  │ TastyTrade API │  │ Polymarket CLOB│  │ Kalshi REST/WS   │  │
│  │ DXLink stream  │  │ yes/no markets │  │ event contracts  │  │
│  │ options flow   │  │ order books    │  │ resolution data  │  │
│  └───────┬────────┘  └───────┬────────┘  └────────┬─────────┘  │
│          │                   │                     │            │
│          └───────────────────┼─────────────────────┘            │
│                              │ unified market state             │
│  ┌───────────────────────────▼──────────────────────────────┐  │
│  │  agent-correlator                                         │  │
│  │  cross-venue divergence · implied probability gap        │  │
│  │  pearson correlation · time-lagged signal scoring        │  │
│  └───────────────────────────┬──────────────────────────────┘  │
│                              │ + sentiment stream               │
│  ┌───────────────────────────┴──────────────────────────────┐  │
│  │  agent-sentiment                                          │  │
│  │  Twitter/X v2 · financial news NLP · Claude Sonnet       │  │
│  │  entity extraction · score: -1.0 → +1.0                  │  │
│  └───────────────────────────┬──────────────────────────────┘  │
│                              │ signal + context                 │
│  ┌───────────────────────────▼──────────────────────────────┐  │
│  │  agent-dispatcher                                         │  │
│  │  Slack · Discord · webhook · ClawBox dashboard           │  │
│  │  confidence gate · human review queue                     │  │
│  └──────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘
         │                                     │
         ▼                                     ▼
  claws-mac-mini :11434               CF Pages dashboard
  Claude Sonnet via OpenClaw          organizedmarket.organizedai.vip
  local inference (optional)
  

Why ClawBox as the Container

ClawBox's Lima-based VM isolation is ideal for a financial intelligence agent: API credentials never touch your host Mac, the VM can be snapshotted before experiments, and the OpenClaw gateway handles multi-agent orchestration without needing to wire up a separate orchestration layer. Everything is already there.

Component Technology Role
ClawBox GUI Tauri + React Native macOS wrapper, one-click VM start/stop
Lima VM Ubuntu 24.04 ARM Isolated execution environment, no host filesystem access
OpenClaw Node.js + Python Agent gateway :18789, multi-agent orchestration, tool registry
agent-signal Python + DXLink WS TastyTrade streaming quotes, options flow, greeks ingestion
agent-poly Python + REST/WS Polymarket CLOB order book, market odds polling
agent-kalshi Python + REST Kalshi event contract prices, resolution tracking
agent-sentiment Python + Claude Sonnet Twitter/X entity scoring, financial news NLP
agent-correlator Python + NumPy Cross-venue divergence, Pearson + lag correlation matrix
agent-dispatcher Python + webhooks Confidence-gated alerts, Slack/Discord/ClawBox UI output
// CLAWBOX SETUP

ClawBox Setup

ClawBox ships as a native macOS app. It manages the entire Lima VM lifecycle — no CLI required. Once installed, OpenClaw runs inside the Ubuntu 24.04 VM and exposes a gateway at localhost:18789 through a port-forwarded bridge.

macOS only. ClawBox requires macOS 13+ (Ventura or later) with Apple Silicon recommended. Lima requires Homebrew. The VM uses ~4GB RAM when fully running OrganizedMarket's 6-agent stack.

1. Install ClawBox

# Option A — Direct DMG download (recommended)
# Visit: https://github.com/coderkk1992/clawbox/releases
# Download ClawBox.dmg → drag to Applications

# Option B — Build from source (for contributors)
git clone https://github.com/coderkk1992/clawbox.git
cd clawbox
npm install
npm run tauri dev

# Homebrew dependency (required by Lima VM manager)
brew install lima qemu

2. Launch VM & Install OpenClaw

# 1. Open ClawBox.app from Applications
# 2. Click "Start VM" — provisions Ubuntu 24.04 via Lima (~2 min first run)
# 3. ClawBox opens an embedded terminal into the VM
# 4. Inside the VM terminal, install OpenClaw:

curl -fsSL https://openclaw.ai/install.sh | bash

# Verify OpenClaw is running
openclaw status
# → OpenClaw gateway running on :18789
# → 0 agents registered

3. Clone OrganizedMarket Into the VM

# Inside ClawBox VM terminal:

git clone https://github.com/Organized-AI/organizedmarket.git
cd organizedmarket

# Install Python dependencies
pip install -r requirements.txt

# Install Node dependencies (for OpenClaw plugin registration)
npm install

4. Wire Agent Config

# Copy and populate environment
cp .env.example .env

# .env contents — replace all placeholder values:
TASTYTRADE_USERNAME=your_tastytrade_username
TASTYTRADE_PASSWORD=your_tastytrade_password
TASTYTRADE_ACCOUNT_NUMBER=your_account_number

POLYMARKET_API_KEY=your_polymarket_api_key
POLYMARKET_SECRET=your_polymarket_secret
POLYMARKET_PASSPHRASE=your_polymarket_passphrase

KALSHI_API_KEY_ID=your_kalshi_key_id
KALSHI_PRIVATE_KEY_PATH=./keys/kalshi_private.pem

TWITTER_BEARER_TOKEN=your_twitter_bearer_token
NEWSAPI_KEY=your_newsapi_key

# Claude routes through OpenClaw OAuth — no ANTHROPIC_API_KEY needed
OPENCLAW_URL=http://localhost:18789
OPENCLAW_CODEX_TOKEN=codex_...   # generated by: openclaw auth token

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...  # optional
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/... # optional

5. Register Agents with OpenClaw

# Register all 6 agents with the OpenClaw gateway
python scripts/register_agents.py

# Verify registration
openclaw agents list
# → agent-signal      [registered]
# → agent-poly        [registered]
# → agent-kalshi      [registered]
# → agent-sentiment   [registered]
# → agent-correlator  [registered]
# → agent-dispatcher  [registered]

# Start the full stack
openclaw start --config openclaw.config.json
# → All 6 agents initializing...
# → TastyTrade session established
# → Polymarket WebSocket connected
# → Kalshi REST polling active
# → Sentiment stream online
# → Correlator ready
# → Dispatcher armed

ClawBox Architecture Internals

┌──────────────────────────────────────────┐
│  ClawBox (Tauri + React)                 │
│  Native macOS UI                         │
├──────────────────────────────────────────┤
│  Lima VM Manager                         │
├──────────────────────────────────────────┤
│  Ubuntu 24.04 VM                         │
│  ┌──────────────────────────────────┐    │
│  │  OpenClaw Agent                  │    │
│  │  Browser · Terminal · File Sys   │    │
│  └──────────────────────────────────┘    │
└──────────────────────────────────────────┘
         ▲
         │  Your files stay on your Mac.
         │  You share only what you upload.
         └──────────────────────────────────
// DATA SOURCES

Data Sources

Three primary data sources feed OrganizedMarket: TastyTrade for live financial market data and options flow, Polymarket for binary prediction market odds, and Kalshi for regulated event contracts. Together they form a complete picture of market-implied probabilities versus hard derivative pricing.

TastyTrade API — Financial Market Data

TastyTrade provides a full open REST API with a WebSocket DXLink streamer for real-time quotes. The SDK supports equities, ETFs, options, futures, and futures options. OrganizedMarket uses it primarily for options chain data, implied volatility surfaces, and streaming quotes on macro-sensitive instruments (SPY, QQQ, /ES, /ZQ, TLT).

# agent-signal/tastytrade_client.py

import requests
import websockets
import json
from dataclasses import dataclass

BASE_URL = "https://api.tastytrade.com"  # Production
# BASE_URL = "https://api.cert.tastyworks.com"  # Sandbox

class TastyTradeClient:
    def __init__(self, username: str, password: str):
        self.session_token = None
        self.dxlink_token = None
        self._authenticate(username, password)

    def _authenticate(self, username: str, password: str):
        """Create a session token. Valid for 24 hours."""
        resp = requests.post(f"{BASE_URL}/sessions", json={
            "login": username,
            "password": password,
            "remember-me": True
        })
        data = resp.json()["data"]
        self.session_token = data["session-token"]
        self.headers = {
            "Authorization": self.session_token,
            "Content-Type": "application/json"
        }

    def get_dxlink_token(self) -> str:
        """Get streaming token for DXLink WebSocket."""
        resp = requests.get(
            f"{BASE_URL}/api-quote-tokens",
            headers=self.headers
        )
        token_data = resp.json()["data"]
        self.dxlink_token = token_data["token"]
        self.dxlink_streamer_url = token_data["streamer-url"]
        return self.dxlink_token

    def get_option_chain(self, symbol: str) -> dict:
        """Full option chain for correlation with prediction markets."""
        resp = requests.get(
            f"{BASE_URL}/option-chains/{symbol}/nested",
            headers=self.headers
        )
        return resp.json()["data"]

    def get_market_metrics(self, symbols: list[str]) -> dict:
        """IV rank, IV percentile, beta-weighted delta for a list of symbols."""
        params = {"symbols[]": symbols}
        resp = requests.get(
            f"{BASE_URL}/market-metrics",
            headers=self.headers,
            params=params
        )
        return resp.json()["data"]["items"]

# DXLink WebSocket streaming — real-time quotes
async def stream_quotes(client: TastyTradeClient, symbols: list[str], callback):
    token = client.get_dxlink_token()
    uri = f"wss://tasty-openapi-ws.dxfeed.com/realtime?token={token}"

    async with websockets.connect(uri) as ws:
        # Authorize
        await ws.send(json.dumps({
            "type": "SETUP", "channel": 0,
            "version": "0.1", "minVersion": "0.1"
        }))
        # Subscribe to quote events
        await ws.send(json.dumps({
            "type": "SUBSCRIBE", "channel": 1,
            "add": [{"type": "Quote", "symbol": s} for s in symbols]
        }))
        async for msg in ws:
            data = json.loads(msg)
            if data.get("type") == "FEED_DATA":
                await callback(data["data"])  # → agent-correlator

Polymarket — Prediction Market Odds

Polymarket uses a Central Limit Order Book (CLOB) model. OrganizedMarket pulls live order books and trades for politically and economically sensitive markets — Fed decisions, election outcomes, GDP prints, CPI surprises — and feeds the implied probabilities directly into the correlation engine for comparison against options-implied probabilities.

# agent-poly/polymarket_client.py

from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds

class PolymarketClient:
    def __init__(self, api_key: str, secret: str, passphrase: str):
        self.client = ClobClient(
            host="https://clob.polymarket.com",
            chain_id=137,  # Polygon
            creds=ApiCreds(
                api_key=api_key,
                api_secret=secret,
                api_passphrase=passphrase
            )
        )

    def get_market(self, condition_id: str) -> dict:
        """Get market metadata including question, resolution criteria."""
        return self.client.get_market(condition_id)

    def get_order_book(self, token_id: str) -> dict:
        """Live order book — bids/asks give implied yes probability."""
        return self.client.get_order_book(token_id)

    def search_markets(self, query: str, active_only: bool = True) -> list:
        """
        Find prediction markets matching financial query terms.
        e.g. query="Federal Reserve rate cut" → relevant contracts
        """
        markets = self.client.get_markets()
        results = []
        for m in markets["data"]:
            if query.lower() in m["question"].lower():
                if not active_only or m["active"]:
                    results.append({
                        "condition_id": m["condition_id"],
                        "question": m["question"],
                        "yes_price": m.get("tokens", [{}])[0].get("price"),
                        "volume": m.get("volume"),
                        "end_date": m.get("end_date_iso")
                    })
        return results

    def get_implied_probability(self, condition_id: str) -> float:
        """
        Mid-market yes price = implied probability.
        Compare this to options-implied probability from TastyTrade.
        """
        book = self.get_order_book(condition_id)
        best_bid = float(book["bids"][0]["price"]) if book["bids"] else 0
        best_ask = float(book["asks"][0]["price"]) if book["asks"] else 1
        return (best_bid + best_ask) / 2

Kalshi — Regulated Event Contracts

Kalshi is CFTC-regulated, making it the cleanest source of prediction market data for US financial events. OrganizedMarket focuses on Kalshi's Fed rate, CPI, GDP, and jobs report markets — these map directly to instruments TastyTrade can stream.

# agent-kalshi/kalshi_client.py

import requests
import time
import jwt
from cryptography.hazmat.primitives import serialization

KALSHI_BASE = "https://trading-api.kalshi.com/trade-api/v2"  # Production
# KALSHI_BASE = "https://demo-api.kalshi.co/trade-api/v2"   # Demo

class KalshiClient:
    def __init__(self, key_id: str, private_key_path: str):
        self.key_id = key_id
        with open(private_key_path, "rb") as f:
            self.private_key = serialization.load_pem_private_key(f.read(), password=None)

    def _headers(self, method: str, path: str) -> dict:
        """HMAC-signed headers required for all Kalshi API calls."""
        ts = str(int(time.time() * 1000))
        message = ts + method.upper() + path
        sig = jwt.encode({"msg": message}, self.private_key, algorithm="RS256")
        return {
            "KALSHI-ACCESS-KEY": self.key_id,
            "KALSHI-ACCESS-SIGNATURE": sig,
            "KALSHI-ACCESS-TIMESTAMP": ts,
            "Content-Type": "application/json"
        }

    def get_markets(self, category: str = "financials") -> list:
        """
        Fetch open markets. category options:
        financials · economic-indicators · monetary-policy
        """
        path = f"/markets?category={category}&status=open"
        resp = requests.get(
            f"{KALSHI_BASE}{path}",
            headers=self._headers("GET", path)
        )
        return resp.json()["markets"]

    def get_market_orderbook(self, ticker: str) -> dict:
        """Order book for a specific market ticker."""
        path = f"/markets/{ticker}/orderbook"
        resp = requests.get(
            f"{KALSHI_BASE}{path}",
            headers=self._headers("GET", path)
        )
        return resp.json()

    def get_yes_price(self, ticker: str) -> float:
        """Yes price (implied probability) for event resolution."""
        book = self.get_market_orderbook(ticker)
        yes_bids = book.get("orderbook", {}).get("yes", [])
        return yes_bids[0][0] / 100 if yes_bids else None

Source Comparison

Feature TastyTrade Polymarket Kalshi
Data type Options, equities, futures Binary outcome markets Regulated event contracts
Streaming Yes — DXLink WS Yes — CLOB WS Polling (REST)
Regulation FINRA/SEC CFTC (prediction mkt) CFTC regulated ✓
Auth Session token (24hr) API key + L2 signing RSA private key JWT
Free tier Yes (account required) Yes (read-only) Yes (demo env)
Correlation use Ground truth pricing Implied probability Regulated prob. signal
// AGENT PIPELINE

The 6-Agent Pipeline

Each agent runs as an independent OpenClaw sub-process inside the ClawBox VM. They communicate via OpenClaw's internal message bus. The correlator consumes outputs from all data agents simultaneously and scores divergence signals. The dispatcher is the only agent that writes to external systems.

ORGANIZEDMARKET — AGENT DATA FLOW

  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
  │ agent-signal │  │  agent-poly  │  │ agent-kalshi │
  │  TastyTrade  │  │  Polymarket  │  │    Kalshi    │
  │  DXLink/REST │  │  CLOB API    │  │  REST + JWT  │
  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘
         │                 │                  │
         │  quote_update   │  odds_update     │  contract_update
         └─────────────────┼──────────────────┘
                           │
                    ┌──────▼────────────────────────┐
                    │     agent-correlator           │
                    │  cross-venue divergence calc   │
                    │  Pearson · lag · Z-score       │
                    └──────┬────────────────────────┘
                           │
              ┌────────────┴───────────────┐
              │  agent-sentiment           │
              │  Twitter/X · news · Claude │
              │  score: -1.0 → +1.0        │
              └────────────┬───────────────┘
                           │ signal + context + confidence
                    ┌──────▼────────────────────────┐
                    │     agent-dispatcher           │
                    │  confidence gate (>0.75 alert) │
                    │  Slack · Discord · ClawBox UI  │
                    └───────────────────────────────┘

Agent Definitions

agent-signal
triggercontinuous — DXLink WebSocket stream + REST polling every 30s
inputsTastyTrade session, watchlist symbols (SPY, QQQ, /ES, /ZQ, TLT, GLD)
actionsStream real-time quotes via DXLink · fetch option chain greeks every 5min · calculate options-implied probability for event dates
output→ message-bus: { symbol, price, iv_rank, options_implied_prob, timestamp }
agent-poly
triggerWebSocket stream + REST polling every 15s for active markets
inputsPolymarket CLOB API · market condition IDs from config watchlist
actionsPoll order books · calculate mid-market yes price · detect large order flow (>$10k notional) · flag sudden odds movement >5% in 60s
output→ message-bus: { market_id, question, yes_prob, volume_24h, odds_delta_1h, timestamp }
agent-kalshi
triggerREST polling every 60s (no WebSocket on free tier)
inputsKalshi REST API · category: monetary-policy, economic-indicators
actionsFetch open financial markets · extract yes price · track resolution dates · cross-reference against TastyTrade expiry calendar
output→ message-bus: { ticker, title, yes_price, close_time, category, timestamp }
agent-sentiment
triggerTwitter/X stream continuous · NewsAPI polling every 5min
inputsTwitter/X v2 filtered stream · NewsAPI financial sources · Claude Sonnet via OpenClaw
actionsFilter X stream by financial keywords + watchlist tickers · Claude scores sentiment per entity (-1 to +1) · extract event signals · calculate aggregate sentiment velocity
output→ message-bus: { entity, sentiment_score, velocity, top_keywords, source_count, timestamp }
agent-correlator
triggeron every message-bus update from signal/poly/kalshi
inputsUnified market state from message-bus · sentiment overlay from agent-sentiment
actionsCalculate Pearson correlation between options-implied prob and prediction market yes price · compute time-lag matrix (does sentiment precede price?) · Z-score divergence vs 30-day rolling mean · classify signal tier: HIGH / MED / LOW
output→ dispatcher: { signal_id, instruments, divergence_score, confidence, evidence, tier }
agent-dispatcher
triggeron correlator output — gate: tier HIGH always; MED requires sentiment confirmation
inputsCorrelated signal + confidence score + evidence summary
actionsRoute HIGH signals to Slack/Discord immediately · queue MED signals for pattern confirmation window · log ALL signals to SQLite for flywheel · generate plain-English summary via Claude
outputSlack/Discord alert · ClawBox dashboard update · signal log entry

Message Bus Schema

# Internal message format — all agents publish/subscribe this schema

{
  "agent": "agent-signal",
  "timestamp": "2025-04-16T14:30:00Z",
  "type": "quote_update",           # quote_update | odds_update | sentiment | signal
  "payload": {
    "symbol": "SPY",
    "price": 528.42,
    "iv_rank": 0.34,                # 0.0–1.0 — low IV = market complacent
    "options_implied_prob": 0.72,   # from ATM options pricing for event date
    "delta_1h": -0.015              # price delta last hour
  }
}

# Correlator output to dispatcher
{
  "agent": "agent-correlator",
  "timestamp": "2025-04-16T14:31:05Z",
  "type": "signal",
  "payload": {
    "signal_id": "SIG-20250416-001",
    "tier": "HIGH",
    "confidence": 0.81,
    "divergence": {
      "tastytrade_implied_prob": 0.72,   # SPY options say 72% chance
      "polymarket_yes_price": 0.54,      # Polymarket says 54%
      "kalshi_yes_price": 0.58,          # Kalshi says 58%
      "gap": 0.16                        # 16pt divergence → signal
    },
    "sentiment_overlay": {
      "entity": "Federal Reserve",
      "score": -0.42,                    # bearish sentiment
      "velocity": "rising_negative"
    },
    "summary": "Options market implies significantly higher probability of Fed hold than prediction markets. Bearish Twitter/X sentiment accelerating. Potential arb between /ZQ options and Kalshi FOMC market.",
    "instruments": ["KXFED-25APR", "/ZQ", "TLT"],
    "lag_correlation": 0.68              # sentiment leads price by ~45min
  }
}
// INTELLIGENCE LAYER

Intelligence Layer

The intelligence layer sits inside agent-correlator and agent-sentiment. It translates raw price feeds and social signals into structured, scored intelligence that a trader can act on.

Correlation Engine

The correlator maintains a rolling state of implied probabilities across all three venues. It computes Pearson correlation between TastyTrade options-implied probabilities and prediction market yes prices, then Z-scores the current divergence against its 30-day history.

# agent-correlator/engine.py

import numpy as np
from collections import deque
from dataclasses import dataclass, field

@dataclass
class MarketState:
    tastytrade_prob: float  # from options pricing
    poly_yes: float         # Polymarket mid-market
    kalshi_yes: float       # Kalshi best bid
    sentiment_score: float  # -1.0 to +1.0
    timestamp: str

class CorrelationEngine:
    def __init__(self, window_days: int = 30):
        self.history: deque[MarketState] = deque(maxlen=window_days * 480)  # ~5min bars
        self.lag_window = 12  # 1 hour at 5min resolution

    def add_state(self, state: MarketState):
        self.history.append(state)

    def compute_divergence(self, state: MarketState) -> dict:
        """
        Primary signal: gap between options-implied probability
        and prediction market consensus.
        """
        tt_prob = state.tastytrade_prob
        pm_consensus = (state.poly_yes + state.kalshi_yes) / 2
        gap = tt_prob - pm_consensus

        # Z-score vs historical gaps
        if len(self.history) > 60:
            hist_gaps = [s.tastytrade_prob - (s.poly_yes + s.kalshi_yes) / 2
                        for s in self.history]
            z_score = (gap - np.mean(hist_gaps)) / (np.std(hist_gaps) + 1e-9)
        else:
            z_score = 0.0

        return {
            "gap": round(gap, 4),
            "z_score": round(z_score, 3),
            "tastytrade_implied": round(tt_prob, 4),
            "pm_consensus": round(pm_consensus, 4),
            "signal_strength": abs(z_score) / 3.0  # normalize 3σ = 1.0
        }

    def compute_sentiment_lag(self) -> float:
        """
        Does sentiment precede price movement?
        Returns correlation coefficient at optimal lag.
        """
        if len(self.history) < self.lag_window * 2:
            return 0.0

        states = list(self.history)
        sentiments = [s.sentiment_score for s in states]
        prices = [s.tastytrade_prob for s in states]

        # Test lag correlations: 0 to lag_window
        best_r, best_lag = 0.0, 0
        for lag in range(1, self.lag_window):
            r = np.corrcoef(sentiments[:-lag], prices[lag:])[0, 1]
            if abs(r) > abs(best_r):
                best_r, best_lag = r, lag

        return best_r  # +/- indicates direction, magnitude indicates predictive power

    def score_signal(self, divergence: dict, sentiment: dict) -> tuple[float, str]:
        """
        Confidence score 0.0–1.0 + tier classification.
        HIGH (>0.75): fire alert immediately
        MED (0.45–0.75): queue for confirmation window
        LOW (<0.45): log to flywheel only
        """
        z = abs(divergence["z_score"])
        gap = abs(divergence["gap"])
        sent_magnitude = abs(sentiment.get("score", 0))
        sent_alignment = 1.0 if (divergence["gap"] * sentiment.get("score", 0)) < 0 else 0.5

        # Weighted confidence formula
        confidence = (
            min(z / 3.0, 1.0) * 0.45 +   # statistical significance
            min(gap / 0.20, 1.0) * 0.30 + # raw gap size (20pt = max)
            sent_magnitude * sent_alignment * 0.25  # sentiment alignment
        )

        tier = "HIGH" if confidence > 0.75 else "MED" if confidence > 0.45 else "LOW"
        return round(confidence, 3), tier

Twitter/X Sentiment Pipeline

The Twitter/X v2 filtered stream listens for tweets containing financial entities and watchlist ticker symbols. Claude Sonnet scores sentiment per entity and calculates velocity — the rate at which sentiment is shifting, which is often more predictive than absolute level.

# agent-sentiment/twitter_stream.py

import tweepy
import asyncio
from openclaw_client import claude_via_openclaw

STREAM_RULES = [
    # Macro events
    {"value": "Federal Reserve OR FOMC OR Jerome Powell -is:retweet lang:en"},
    {"value": "CPI OR inflation OR \"jobs report\" -is:retweet lang:en"},
    {"value": "recession OR \"rate cut\" OR \"rate hike\" -is:retweet lang:en"},
    # Instruments (expand for your watchlist)
    {"value": "SPY OR QQQ OR \"S&P 500\" -is:retweet lang:en"},
    {"value": "Polymarket OR Kalshi OR \"prediction market\" -is:retweet lang:en"},
]

SENTIMENT_PROMPT = """
Analyze this tweet for financial market sentiment.

Tweet: {tweet_text}

Return JSON only:
{{
  "entities": ["list of financial entities mentioned"],
  "primary_entity": "main subject (Fed, SPY, inflation, etc.)",
  "sentiment": -1.0 to 1.0 (-1=very bearish, 0=neutral, +1=very bullish),
  "event_signal": true/false (does this reference a specific upcoming event?),
  "event_date": "YYYY-MM-DD or null",
  "confidence": 0.0 to 1.0
}}
No commentary. JSON only.
"""

class SentimentStream(tweepy.StreamingClient):
    def __init__(self, bearer_token: str, message_bus, openclaw_url: str):
        super().__init__(bearer_token)
        self.bus = message_bus
        self.openclaw_url = openclaw_url
        self.entity_buffer = {}  # accumulate before velocity calc

    def on_tweet(self, tweet):
        asyncio.create_task(self._process(tweet.text))

    async def _process(self, text: str):
        response = await claude_via_openclaw(
            self.openclaw_url,
            prompt=SENTIMENT_PROMPT.format(tweet_text=text[:500]),
            max_tokens=200
        )

        try:
            sentiment_data = json.loads(response)
            entity = sentiment_data["primary_entity"]
            score = float(sentiment_data["sentiment"])

            # Update entity buffer and calculate velocity
            if entity not in self.entity_buffer:
                self.entity_buffer[entity] = deque(maxlen=20)
            self.entity_buffer[entity].append(score)

            # Velocity = delta in rolling mean over last 5 vs previous 5
            buf = list(self.entity_buffer[entity])
            velocity = np.mean(buf[-5:]) - np.mean(buf[-10:-5]) if len(buf) >= 10 else 0

            await self.bus.publish({
                "type": "sentiment",
                "entity": entity,
                "sentiment_score": score,
                "velocity": round(velocity, 4),
                "event_signal": sentiment_data.get("event_signal", False),
                "event_date": sentiment_data.get("event_date"),
            })
        except (json.JSONDecodeError, KeyError):
            pass  # malformed response — skip

Signal Summary Generation

Before dispatching any alert, Claude generates a plain-English summary that includes data provenance, confidence rationale, and relevant context. The goal is a summary that could be handed to a trader who has no context and they immediately understand the opportunity.

SIGNAL_SUMMARY_PROMPT = """
You are a market intelligence analyst. Summarize this trading signal for a professional trader.

Signal data:
- TastyTrade options-implied probability: {tt_prob:.0%}
- Polymarket yes price: {poly_yes:.0%}
- Kalshi yes price: {kalshi_yes:.0%}
- Divergence gap: {gap:.1%} ({z_score:.1f} standard deviations from 30-day mean)
- Sentiment on {entity}: {sentiment_score:+.2f} (velocity: {velocity:+.3f})
- Instruments: {instruments}
- Confidence score: {confidence:.0%} ({tier})

Write 3-4 sentences:
1. What the signal is and where the divergence lies
2. What the sentiment context suggests
3. What instruments are relevant and how
4. What a trader should do to investigate further (NO trading advice — information only)

Be direct. Use financial terminology. No hedging language.
"""

Intelligence Data Flow

SENTIMENT + PRICE → SIGNAL LIFECYCLE

Twitter/X stream ──┐
NewsAPI polling ───┼──→ agent-sentiment ──→ score (-1 to +1)
                   │    (Claude NLP)         velocity calc
                   │
TastyTrade DXLink ─┼──→ options-implied prob
                   │    IV rank + delta
                   │
Polymarket CLOB ───┼──→ yes price (mid)
                   │    order flow delta
                   │
Kalshi REST ───────┘──→ yes price
                        resolution timeline

All streams ──→ agent-correlator
               · Pearson correlation matrix
               · Z-score vs 30-day history
               · Lag analysis (sentiment → price)
               · Confidence + tier scoring
                    │
                 HIGH (>0.75) ───→ immediate alert + Claude summary
                 MED (0.45–0.75) → 15-min confirmation window
                 LOW (<0.45) ────→ flywheel log only
// STACK & CONVENTIONS

Stack & Conventions

Python-first, OpenClaw-native agent architecture. All agents are independent Python processes registered with the OpenClaw gateway. Shared types and utilities live in packages/. Same monorepo conventions as the broader Organized AI codebase.

Runtime

Python 3.12 OpenClaw :18789 ClawBox / Lima VM Ubuntu 24.04 NumPy SQLite (signal log)

Key Dependencies

PackagePurpose
tastytradeOfficial Python SDK — sessions, option chains, DXLink streamer
py-clob-clientPolymarket CLOB API — order books, markets, trades
tweepyTwitter/X v2 filtered stream client
websocketsDXLink WebSocket streaming for TastyTrade real-time quotes
numpyPearson correlation, rolling statistics, Z-score calculation
cryptography / pyjwtKalshi RSA signature auth
newsapi-pythonFinancial news sources — Reuters, Bloomberg, WSJ aggregation
sqlalchemySignal log persistence — all signals stored for flywheel replay
pydanticMessage bus schema validation across all agents
anthropicClaude Sonnet — sentiment NLP + signal summary (via OpenClaw OAuth)

Monorepo Layout

organizedmarket/
  agents/
    agent-signal/           # TastyTrade ingestion
      tastytrade_client.py
      dxlink_stream.py
      options_analyzer.py
    agent-poly/             # Polymarket CLOB
      polymarket_client.py
      order_book_tracker.py
    agent-kalshi/           # Kalshi event markets
      kalshi_client.py
      contract_tracker.py
    agent-sentiment/        # Twitter/X + news NLP
      twitter_stream.py
      news_poller.py
      sentiment_scorer.py
    agent-correlator/       # Cross-venue intelligence
      engine.py
      lag_analyzer.py
      signal_scorer.py
    agent-dispatcher/       # Alert routing
      dispatcher.py
      formatters.py
  packages/
    message_bus/            # Internal pub/sub (asyncio queues)
    schemas/                # Pydantic models for all message types
    openclaw_client/        # OpenClaw gateway HTTP client
    db/                     # SQLite signal log helpers
  scripts/
    register_agents.py      # Register all 6 agents with OpenClaw
    setup_keys.sh           # Generate and store all API keys
    backfill.py             # Historical signal replay for correlation testing
  dashboard/                # CF Pages — signal feed + correlation viewer
    index.html
    assets/
  openclaw.config.json      # Agent registry + message bus config
  .env.example
  requirements.txt
  CLAUDE.md                 # Agent conventions for Claude Code

Conventions

# All agents follow this contract:
# 1. Register with OpenClaw on startup
# 2. Subscribe to relevant message-bus topics
# 3. Publish typed, validated messages only (Pydantic schemas)
# 4. Never write to external systems (dispatcher only)
# 5. Log all errors to OpenClaw structured log
# 6. Store raw data in SQLite for flywheel replay

# openclaw.config.json — agent registry
{
  "gateway_port": 18789,
  "agents": [
    { "name": "agent-signal",     "entry": "agents/agent-signal/main.py",     "restart": "always" },
    { "name": "agent-poly",       "entry": "agents/agent-poly/main.py",       "restart": "always" },
    { "name": "agent-kalshi",     "entry": "agents/agent-kalshi/main.py",     "restart": "on-failure" },
    { "name": "agent-sentiment",  "entry": "agents/agent-sentiment/main.py",  "restart": "always" },
    { "name": "agent-correlator", "entry": "agents/agent-correlator/main.py", "restart": "always" },
    { "name": "agent-dispatcher", "entry": "agents/agent-dispatcher/main.py", "restart": "on-failure" }
  ],
  "message_bus": { "type": "asyncio", "max_queue": 10000 },
  "claude_model": "claude-sonnet-4-6"
}
// DEPLOY & RUN

Deploy & Run

Two deploy targets: the ClawBox agent stack (runs locally inside the VM) and the CF Pages dashboard (public-facing signal feed + docs, deployed via Wrangler CLI). No CI/CD required — run from your Mac.

1. Configure API Keys

cp .env.example .env

# Fill all placeholder values — see Sources section for how to obtain each key
# DO NOT commit .env to git

# Verify .env is in .gitignore
echo ".env" >> .gitignore
echo "keys/" >> .gitignore

2. TastyTrade Sandbox (Recommended First)

# Use TastyTrade's certification environment before connecting live account
# .env: switch BASE_URL to sandbox

BASE_URL=https://api.cert.tastyworks.com  # Sandbox
# BASE_URL=https://api.tastytrade.com     # Production (uncomment when ready)

# Create a sandbox account at: https://developer.tastytrade.com
# Sandbox has all API features including DXLink streaming

# Kalshi demo environment
KALSHI_BASE=https://demo-api.kalshi.co/trade-api/v2  # Demo
# KALSHI_BASE=https://trading-api.kalshi.com/trade-api/v2  # Production

3. Start OrganizedMarket (ClawBox VM)

# Inside ClawBox VM terminal:

cd ~/organizedmarket

# Register agents and start the full stack
python scripts/register_agents.py
openclaw start --config openclaw.config.json

# Watch agent status
openclaw agents status
# → agent-signal       [running] pid:1234  uptime:00:02:14
# → agent-poly         [running] pid:1235  uptime:00:02:13
# → agent-kalshi       [running] pid:1236  uptime:00:02:13
# → agent-sentiment    [running] pid:1237  uptime:00:02:12
# → agent-correlator   [running] pid:1238  uptime:00:02:11
# → agent-dispatcher   [running] pid:1239  uptime:00:02:11

# View live signal feed
openclaw logs agent-dispatcher --follow

# View correlation engine output
openclaw logs agent-correlator --follow

4. Deploy Dashboard to CF Pages

# From your Mac (outside ClawBox VM):
cd organizedmarket/dashboard

# First deploy — create CF Pages project
wrangler pages project create organizedmarket-arch \
  --production-branch=main

# Deploy docs/dashboard
wrangler pages deploy . \
  --project-name=organizedmarket-arch \
  --branch=main \
  --commit-dirty=true

# → Published: https://organizedmarket-arch.pages.dev

# Custom domain (optional)
wrangler pages domain add organizedmarket.organizedai.vip \
  --project-name=organizedmarket-arch

5. Push Wrangler Secrets (Dashboard Workers)

# If running a CF Worker alongside the dashboard for live signal relay:
echo $OPENCLAW_URL         | wrangler secret put OPENCLAW_URL         --name organizedmarket-relay
echo $OPENCLAW_CODEX_TOKEN | wrangler secret put OPENCLAW_CODEX_TOKEN --name organizedmarket-relay

# Account metadata
CLOUDFLARE_ACCOUNT_ID=YOUR_ACCOUNT_ID \
  wrangler deploy --name organizedmarket-relay \
  --config workers/relay/wrangler.toml

Deploying These Docs

# The exact pattern used to deploy this guide:
wrangler pages project create organizedmarket-arch --production-branch=main

wrangler pages deploy /path/to/organizedmarket/dashboard \
  --project-name=organizedmarket-arch \
  --branch=main \
  --commit-dirty=true

Architecture Options

A — Cloud onlyB — Local onlyC — ClawBox ✓D — ExoClaw bridge
Claude cost High ($20+/mo) Free (local model) Low ($4–8/mo) Free
Signal quality Best Good Best Good
Setup complexity Low Medium Low High
Reliability Best Mac-dependent Good Mac-dependent
Isolation Full None Full (Lima VM) Partial

Operational Checklist

Never auto-trade
OrganizedMarket surfaces signals only. All alerts include confidence score and provenance. Trading decisions are human-only.
Sandbox first
Run TastyTrade sandbox + Kalshi demo for minimum 48 hours before switching to production credentials. Validate signal quality against known historical events.
Rotate TastyTrade sessions
Session tokens expire every 24 hours. agent-signal handles automatic re-auth. Monitor for auth failures in OpenClaw logs.
Twitter API rate limits
v2 filtered stream is 1 connection per account. Do not start multiple agent-sentiment instances. Basic tier: 500,000 tweets/month read.
Signal log review
Review SQLite signal log weekly. Feed high-confidence signals that preceded market moves into the flywheel for correlation weight tuning.
ClawBox VM snapshots
Snapshot the Lima VM before any major config change. Restore takes <60 seconds. Store snapshots outside ClawBox working directory.

Quick Links

ResourceURL
GitHubgithub.com/Organized-AI/organizedmarket — agents, scripts, dashboard
TastyTrade APIdeveloper.tastytrade.com — REST docs + DXLink WS
Polymarket Docsdocs.polymarket.com — CLOB API reference
Kalshi APIkalshi.com/docs/api — REST + auth guide
ClawBox Repogithub.com/coderkk1992/clawbox — source + releases
OpenClawgithub.com/openclaw/openclaw — gateway + agent registry