Mootlib
A Python library for finding similar questions across prediction markets.
Features
- Search for similar questions across multiple prediction market platforms
- Access historical market data and probabilities
- Compare questions using semantic similarity
- Automatic caching and data management
- Direct access to market data and embeddings
Installation
pip install mootlib
Environment Setup
Required Environment Variables
The library requires several environment variables to function:
MOOTLIB_ENCRYPTION_KEY: Required for decrypting market dataDEEPINFRA_TOKEN: Required for computing embeddingsGJO_EMAILandGJO_PASSWORD: Optional, for Good Judgment Open access
You can set these up in two ways:
1. Using a .env file (recommended for local development)
Create a .env file in your project root:
MOOTLIB_ENCRYPTION_KEY="your-key-here"
DEEPINFRA_TOKEN="your-token-here"
GJO_EMAIL="your-email@example.com" # Optional
GJO_PASSWORD="your-password" # Optional
Then in your Python code:
from dotenv import load_dotenv
load_dotenv() # Load environment variables from .env
from mootlib import MootlibMatcher
matcher = MootlibMatcher()
2. Setting environment variables directly
# Unix/macOS
export MOOTLIB_ENCRYPTION_KEY="your-key-here"
export DEEPINFRA_TOKEN="your-token-here"
# Windows PowerShell
$env:MOOTLIB_ENCRYPTION_KEY="your-key-here"
$env:DEEPINFRA_TOKEN="your-token-here"
3. For GitHub Actions
Add these secrets in your repository's Settings → Secrets and Variables → Actions:
MOOTLIB_ENCRYPTION_KEYDEEPINFRA_TOKENGJO_EMAIL(optional)GJO_PASSWORD(optional)
Then use them in your workflow:
env:
MOOTLIB_ENCRYPTION_KEY: ${{ secrets.MOOTLIB_ENCRYPTION_KEY }}
DEEPINFRA_TOKEN: ${{ secrets.DEEPINFRA_TOKEN }}
Quick Start
from mootlib import MootlibMatcher
# Initialize the matcher
matcher = MootlibMatcher()
# Find similar questions
similar = matcher.find_similar_questions(
"Will Russia invade Moldova in 2024?",
n_results=3,
min_similarity=0.7
)
# Print the results
for question in similar:
print(f"\n{question}")
API Reference
MootlibMatcher
The main interface for finding similar questions across prediction markets.
matcher = MootlibMatcher(cache_duration_minutes=30)
Parameters:
cache_duration_minutes: How long to keep downloaded data in cache (default: 30)
Properties
markets_df
Access the raw markets DataFrame containing all prediction market data:
markets_df = matcher.markets_df
The DataFrame contains columns:
question: The market question textsource_platform: Platform where the market is fromformatted_outcomes: Current probabilities/outcomesurl: Link to the original marketn_forecasters: Number of forecastersvolume: Trading volume/liquiditypublished_at: Publication datetime
embeddings_df
Access the embeddings DataFrame containing question vectors:
embeddings_df = matcher.embeddings_df
The DataFrame contains columns:
text: The question textembedding: The numerical embedding vector
Note: Embeddings are computed on-demand and cached for future use.
find_similar_questions
similar = matcher.find_similar_questions(
query="Will Tesla stock reach $300 in 2024?",
n_results=5,
min_similarity=0.5
)
Parameters:
query: The question to find similar matches forn_results: Number of similar questions to return (default: 5)min_similarity: Minimum similarity score 0-1 (default: 0.5)
Returns a list of SimilarQuestion objects with the following attributes:
question: The text of the prediction market questionsimilarity_score: How similar this question is to the query (0-1)source_platform: The platform where this question was foundformatted_outcomes: String representation of possible outcomes and probabilitiesurl: URL to the original market (optional)n_forecasters: Number of people who made predictions (optional)volume: Trading volume or liquidity (optional)published_at: When the market was published (optional)
Examples
Finding Similar Market Questions
from mootlib import MootlibMatcher
matcher = MootlibMatcher()
# Search for AI-related questions
ai_questions = matcher.find_similar_questions(
"Will AGI be achieved by 2025?",
n_results=3,
min_similarity=0.7
)
# Search for geopolitical questions
geo_questions = matcher.find_similar_questions(
"Will China invade Taiwan in 2024?",
n_results=3,
min_similarity=0.7
)
# Print results
for q in ai_questions + geo_questions:
print(f"\n{q}\n{'=' * 80}")
Accessing Market Details
from mootlib import MootlibMatcher
matcher = MootlibMatcher()
# Find similar questions and access their details
similar = matcher.find_similar_questions("Will SpaceX reach Mars by 2025?")
for q in similar:
print(f"\nQuestion: {q.question}")
print(f"Platform: {q.source_platform}")
print(f"Current Probabilities: {q.formatted_outcomes}")
if q.url:
print(f"Market URL: {q.url}")
if q.n_forecasters:
print(f"Number of Forecasters: {q.n_forecasters}")
print("-" * 80)
Accessing Raw Data
from mootlib import MootlibMatcher
matcher = MootlibMatcher()
# Get all market data
markets_df = matcher.markets_df
print(f"Total markets: {len(markets_df)}")
print("\nMarkets by platform:")
print(markets_df["source_platform"].value_counts())
# Get question embeddings
embeddings_df = matcher.embeddings_df
print(f"\nTotal questions with embeddings: {len(embeddings_df)}")
# Filter markets by platform
manifold_markets = markets_df[markets_df["source_platform"] == "Manifold"]
print(f"\nManifold markets: {len(manifold_markets)}")
# Get high-volume markets
high_volume = markets_df[markets_df["volume"] > 1000]
print(f"\nHigh volume markets: {len(high_volume)}")
Development
Local Setup
- Clone the repository
git clone https://github.com/vigji/mootlib.git
cd mootlib
- Install dependencies with uv
pip install uv
uv venv
source .venv/bin/activate # On Unix/macOS
# or
.venv\Scripts\activate # On Windows
uv pip install -e ".[dev]"
Code Quality
We use Ruff for all Python linting and formatting:
# Format code
ruff format .
# Run linter
ruff check .
# Run linter with automatic fixes
ruff check --fix .
Repository Maintenance
Versioning and Releases
We use Git tags for versioning. The version number is automatically derived from the latest tag using hatch-vcs.
To create a new release, you have two options:
- Quick Release (via Git tag):
# Create and push a new version tag (e.g., v0.1.1)
git tag -a v0.1.1 -m "Description of changes"
git push origin v0.1.1
This will automatically trigger the release workflow.
- Full Release (via GitHub UI):
- Create and push a tag as above
- Go to GitHub -> Releases -> Create a new release
- Choose the tag you just pushed
- Add detailed release notes
- Click "Publish release"
In both cases, the release workflow will automatically:
- Run all tests
- If tests pass, build the package
- Publish to PyPI using trusted publishing
Note: Using the GitHub UI method allows you to add more detailed release notes and attachments, but both methods will publish to PyPI.
Pre-commit Hooks
We use pre-commit hooks to ensure code quality. Install them with:
pre-commit install
This will automatically run Ruff and other checks before each commit.
Code Style Guidelines
- Maximum line length: 88 characters (enforced by Ruff)
- Use pathlib over os.path
- Use functions only where you see opportunity for code reuse
- Use classes sparingly and when it makes sense over functions
- Use loops to streamline operations repeated more than once
- Document briefly middle-length functions, fully annotate only complex ones
Running Tests
pytest
Type Checking
mypy mootlib tests
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for mootlib 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mootlib-0.3.0.tar.gz | 3.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mootlib-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.0 MB
Release files / mootlib-0.3.0.tar.gz
| Download URL | mootlib-0.3.0.tar.gz |
|---|---|
| Size | 3.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4e579b4952686dee3d00596e486e71ae5fb8c4aecea88204396c7682209e382b
|
|
BLAKE2b-256 checksum How to use checksums |
fe9406a51b14578a163fc89c6e74b8fa5b7f9d89f0e5634dda2988274cff3433
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 14, 2025.
Transparency logRelease files / mootlib-0.3.0-py3-none-any.whl
| Download URL | mootlib-0.3.0-py3-none-any.whl |
|---|---|
| Size | 35.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9385aadd9a7d0a76c111b0e10b01cef039444c59a39a4bf0076f1ffa9ff905c4
|
|
BLAKE2b-256 checksum How to use checksums |
1626bce88db6d9436c4b26c9be14a356d51a876b9f06af126c6ff09b3cb10bdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 14, 2025.
Transparency log