> ## Documentation Index
> Fetch the complete documentation index at: https://mathematicalcompany.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Knowledge Graph

> SQLite graph store for markets, events, and their relationships.

Stores markets, events, exchanges, and other entities as nodes. Connects them with typed, weighted edges (correlations, hedges, part-of). Records timestamped facts about each entity. All SQLite, no external dependencies.

## Quick Start

```python theme={null}
from horizon.fund import KnowledgeGraph

kg = KnowledgeGraph()

kg.add_entity("will-trump-win", "market", "Will Trump win?", properties={"exchange": "polymarket"})
kg.add_entity("us-election-2024", "event", "US Election 2024")
kg.add_entity("will-harris-win", "market", "Will Harris win?", properties={"exchange": "polymarket"})

kg.add_relationship("will-trump-win", "us-election-2024", "part_of")
kg.add_relationship("will-harris-win", "us-election-2024", "part_of")
kg.add_relationship("will-trump-win", "will-harris-win", "correlated_with", weight=0.95)

kg.record_fact(
    entity_id="will-trump-win",
    fact_type="edge_detected",
    content="MM strategy shows Sharpe=1.8 in backtest",
    confidence=0.85,
    source="backtest",
    metadata={"sharpe": 1.8, "strategy": "political_mm"},
)

correlated = kg.correlated_markets("will-trump-win", min_weight=0.5)
context = kg.market_context("will-trump-win")
opps = kg.surface_opportunities(min_confidence=0.7, lookback_hours=48.0)

kg.close()
```

When using FundManager, the graph is created automatically:

```python theme={null}
fund = FundManager(FundConfig(total_capital=100_000))
kg = fund.knowledge_graph
```

## Schema

<CardGroup cols={3}>
  <Card title="entities" icon="circle-nodes">
    Markets, events, categories, exchanges, assets, people, organizations. Each has a type, name, JSON properties, and HMAC signature.
  </Card>

  <Card title="relationships" icon="arrows-left-right">
    Directed typed edges between entities. Types: `correlated_with`, `caused_by`, `part_of`, `hedges`, `competes_with`, `related_to`, `influences`, `depends_on`. Each has a weight and validity window.
  </Card>

  <Card title="facts" icon="clipboard-list">
    Timestamped assertions about entities. Types: `observation`, `signal`, `outcome`, `correlation`, `price_move`, `settlement`, `edge_detected`, `regime_change`. Each has a confidence score and optional expiry.
  </Card>
</CardGroup>

## Entities

Seven types: `market`, `event`, `category`, `exchange`, `asset`, `person`, `organization`.

```python theme={null}
# Create or update (upserts on conflict)
kg.add_entity("btc-above-100k", "market", "BTC above $100k by June", properties={"exchange": "kalshi"})

# Lookup
entity = kg.get_entity("btc-above-100k")

# Search by type and/or name
markets = kg.find_entities(entity_type="market", limit=50)
matches = kg.find_entities(name_pattern="trump", limit=20)

# Delete (cascades to relationships and facts)
kg.remove_entity("btc-above-100k")
```

## Relationships

Directed, weighted, temporal. Both endpoints must exist. A unique constraint on `(source, target, type, valid_from)` prevents duplicates.

```python theme={null}
rel = kg.add_relationship(
    source_id="will-trump-win",
    target_id="will-harris-win",
    rel_type="correlated_with",
    weight=0.92,
    properties={"correlation": -0.92, "source": "backtest"},
)

# Query by direction
rels = kg.get_relationships("will-trump-win", direction="outgoing", rel_type="correlated_with")
rels = kg.get_relationships("will-trump-win", direction="both", active_only=True)

# Deactivate without deleting
kg.expire_relationship(rel_id=42)
```

Every relationship has `valid_from` and `valid_to`. When `valid_to` is NULL, it is active. Expiring a relationship sets `valid_to = now` so the historical record is preserved.

## Facts

Assertions about entities with confidence (0.0 to 1.0), source tracking, and optional expiry.

```python theme={null}
fact = kg.record_fact(
    entity_id="will-trump-win",
    fact_type="signal",
    content="Polling shift: +3% in swing states",
    confidence=0.75,
    source="research",
    metadata={"poll_source": "538", "swing_states": ["PA", "MI", "WI"]},
    expires_at=time.time() + 86400,
)

# Filter by entity, type, source, confidence, time
facts = kg.get_facts(entity_id="will-trump-win", active_only=True)
facts = kg.get_facts(fact_type="signal", source="research", min_confidence=0.7, limit=50)
facts = kg.get_facts(since=time.time() - 86400)
```

Fills use confidence 1.0. Backtest edges scale confidence with trade count. Price moves expire after 24h.

## Graph Queries

```python theme={null}
# BFS neighbors (depth capped at 3)
result = kg.neighbors("will-trump-win", depth=2, rel_types=["correlated_with", "hedges"])

# Shortest path (depth capped at 5)
path = kg.find_path("will-trump-win", "btc-above-100k", max_depth=4)

# Markets correlated above a threshold
correlated = kg.correlated_markets("will-trump-win", min_weight=0.5)

# Markets linked to an event
opps = kg.event_opportunities("us-election-2024")
```

## Aggregated Queries

```python theme={null}
# Full context for a market: entity + 2-hop neighbors + facts + correlations
ctx = kg.market_context("will-trump-win")

# Correlation clusters (connected components)
clusters = kg.detect_cross_correlations(min_weight=0.3)

# Recent high-confidence facts
opps = kg.surface_opportunities(fact_types=["edge_detected", "signal"], min_confidence=0.7, lookback_hours=48.0)
```

## Maintenance

```python theme={null}
# Remove expired facts, old low-confidence data, stale relationships
removed = kg.prune(max_age_days=90.0, min_confidence=0.1)

# Counts by type
stats = kg.stats()

# Export subset for debugging
subgraph = kg.export_subgraph(["will-trump-win", "will-harris-win"])
```

When running inside FundManager, pruning runs automatically every 200 oversight ticks with a 90-day cutoff.
