Official Python SDK for Discourses — Era-calibrated financial sentiment analysis
Project description
discourses.io Python SDK
Official Python SDK for discourses.io — the financial social media platform and financial language processing API
📄 Read the Whitepaper · 🔬 Methodology · 📖 Documentation · 🔑 Get API Key
Why discourses.io?
discourses.io is a financial social media platform and financial language processing API built for the modern market.
Traditional sentiment analysis treats language as static. But financial language evolves—"diamond hands" meant nothing in 2008, but signals strong conviction today. discourses.io solves this with era-calibrated lexicons built on peer-reviewed academic research.
| Era | Period | What It Captures |
|---|---|---|
| primitive | Pre-2015 | Traditional financial vocabulary, formal market language |
| meme | 2015–2021 | Rise of retail trading, WSB culture, crypto slang |
| present | 2021–now | Modern market discourse, post-meme institutionalization |
Installation
pip install discourses
Quick Start
from discourses import Discourses
client = Discourses(api_key="your-api-key")
result = client.analyze("Strong growth with excellent outlook ahead")
print(result.label) # "very_bullish"
print(result.outlook) # 0.99
API Reference
🔑 Initialize the Client
Every request requires authentication with your API key. Get yours at discourses.io/dashboard.
from discourses import Discourses
client = Discourses(api_key="your-api-key")
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Your discourses.io API key |
base_url |
str |
https://discourses.io/api/v1 |
API base URL |
timeout |
int |
30 |
Request timeout in seconds |
Endpoints
📊 Analyze — Single Text Sentiment
POST /analyze— Documentation
Analyze sentiment of any financial text. Returns classification, confidence, and detailed sentiment scores.
from discourses import Discourses
# Initialize client
client = Discourses(api_key="your-api-key")
# Analyze text
result = client.analyze("Strong growth with excellent outlook ahead")
# Access the results
print(f"Label: {result.label}")
print(f"Confidence: {result.confidence:.2%}")
print(f"Outlook: {result.outlook:.4f}")
print(f"Bullish: {result.scores['bullish']:.4f}")
print(f"Bearish: {result.scores['bearish']:.4f}")
print(f"Words: {result.word_count}")
Expected Output:
Label: very_bullish
Confidence: 80.05%
Outlook: 0.9257
Bullish: 0.4917
Bearish: 0.2981
Words: 6
Response Object: AnalysisResult
| Field | Type | Description |
|---|---|---|
label |
str |
"very_bullish", "bullish", "neutral", "bearish", "very_bearish" |
confidence |
float |
Model confidence (0.0 to 1.0) |
outlook |
float |
Overall sentiment score (0.0 to 1.0) |
scores |
dict |
Detailed scores: bullish, bearish, neutral, confusion |
word_count |
int |
Number of words analyzed |
matched_count |
int |
Sentiment words matched |
Helper Properties:
result.is_bullish→Trueif label contains "bullish"result.is_bearish→Trueif label contains "bearish"result.is_neutral→Trueif label is "neutral"
🔄 Compare Eras — Cross-Era Analysis
POST /analyze/compare-eras— Documentation
Analyze how the same text is interpreted across different market eras. Essential for understanding semantic drift and backtesting strategies.
from discourses import Discourses
# Initialize client
client = Discourses(api_key="your-api-key")
# Compare sentiment across eras
result = client.compare_eras(
text="This stock is going to the moon! Diamond hands!",
eras=["primitive", "meme", "present"]
)
# View per-era results
print("Era-by-Era Sentiment:")
print("-" * 50)
for era, data in result.results.items():
label = data['classification']['label']
outlook = data['scores']['outlook']
print(f" {era:12} {label:14} (outlook: {outlook:.4f})")
# Check semantic drift
print()
print(f"Drift Direction: {result.drift['direction']}")
print(f"Drift Magnitude: {result.drift['magnitude']:.4f}")
print(f"Peak Era: {result.drift['peak_era']}")
Expected Output:
Era-by-Era Sentiment:
--------------------------------------------------
primitive bullish (outlook: 0.6912)
meme very_bullish (outlook: 0.9933)
present very_bullish (outlook: 0.9977)
Drift Direction: positive_shift
Drift Magnitude: 0.3065
Peak Era: present
💡 Notice how "diamond hands" and "to the moon" have much stronger bullish signals in the meme and present eras compared to primitive!
Response Object: CompareResult
| Field | Type | Description |
|---|---|---|
results |
dict |
Per-era analysis results |
drift |
dict |
Semantic drift metrics |
meta |
dict |
Processing metadata |
Drift Fields:
| Field | Type | Description |
|---|---|---|
direction |
str |
"positive_shift", "negative_shift", or "stable" |
magnitude |
float |
Size of the drift (0.0 to 1.0) |
min_era |
str |
Era with lowest sentiment |
peak_era |
str |
Era with highest sentiment |
⚡ Batch — High-Volume Processing
POST /analyze/batch— Documentation
Efficiently analyze multiple texts in a single request. Perfect for processing feeds, historical data, or real-time streams.
from discourses import Discourses
# Initialize client
client = Discourses(api_key="your-api-key")
# Texts to analyze (with custom IDs)
texts = [
{"id": "post_1", "text": "Diamond hands! This is going to the moon"},
{"id": "post_2", "text": "Bearish on this one, expecting a pullback"},
{"id": "post_3", "text": "Strong growth with excellent outlook ahead"},
]
# Batch analyze with specific era
result = client.batch(texts=texts, era="meme")
# Process results
print("Batch Sentiment Analysis")
print("=" * 55)
for post_id, data in result.results.items():
label = data['classification']['label']
outlook = data['scores']['outlook']
emoji = "🟢" if "bullish" in label else "🔴" if "bearish" in label else "⚪"
print(f"{emoji} {post_id}: {label:14} (outlook: {outlook:.4f})")
print()
print(f"Processed: {result.meta['texts_processed']}")
print(f"Failed: {result.meta['texts_failed']}")
Expected Output:
Batch Sentiment Analysis
=======================================================
🟢 post_1: bullish (outlook: 0.6735)
🟢 post_2: very_bullish (outlook: 0.9353)
🟢 post_3: very_bullish (outlook: 0.9257)
Processed: 3
Failed: 0
Response Object: BatchResult
| Field | Type | Description |
|---|---|---|
results |
dict |
Results keyed by your custom IDs |
meta |
dict |
Processing metadata |
Meta Fields:
| Field | Type | Description |
|---|---|---|
era |
str |
Era used for analysis |
texts_processed |
int |
Successfully processed count |
texts_failed |
int |
Failed count |
processing_time_ms |
int |
Total processing time |
Era Selection Guide
| Use Case | Recommended Era |
|---|---|
| Modern social media sentiment | present |
| Meme stock / crypto analysis | meme |
| Traditional financial news | primitive |
| Understanding semantic drift | compare_eras() |
# Modern analysis
client.analyze(text, era="present")
# Meme-era analysis (WSB, crypto culture)
client.analyze(text, era="meme")
# Traditional financial language
client.analyze(text, era="primitive")
# Compare across all eras
client.compare_eras(text, eras=["primitive", "meme", "present"])
Error Handling
The SDK provides typed exceptions for robust error handling:
from discourses import (
Discourses,
AuthenticationError,
RateLimitError,
ValidationError,
DiscoursesError,
)
client = Discourses(api_key="your-api-key")
try:
result = client.analyze("Market analysis text")
except AuthenticationError:
# Invalid or expired API key
print("Check your API key at https://discourses.io/dashboard")
except RateLimitError as e:
# Too many requests
print(f"Rate limited. Retry after {e.retry_after} seconds")
except ValidationError as e:
# Invalid input (empty text, too long, etc.)
print(f"Invalid input: {e.message}")
except DiscoursesError as e:
# Catch-all for other API errors
print(f"API error: {e}")
Links
| 📄 | Whitepaper Academic research & methodology |
📖 | Documentation Full API reference |
| 🔬 | Methodology How era-calibration works |
🔑 | Dashboard Get your API key |
| 💬 | Issues Report bugs & requests |
📦 | PyPI Package & versions |
License
MIT License — see LICENSE for details.
Built with ❤️ by discourses.io
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file discourses-1.0.5.tar.gz.
File metadata
- Download URL: discourses-1.0.5.tar.gz
- Upload date:
- Size: 17.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55ba8bcf74d96a3f6b962d09e879939990b0cdbfb6032249a93331fbd7f2a424
|
|
| MD5 |
dcc7958cb5a964e9e5a21797c1bf6b58
|
|
| BLAKE2b-256 |
dd10b67f469680757126910ddf486dbc3cbb1e72aab7286914e6dc70419cf904
|
File details
Details for the file discourses-1.0.5-py3-none-any.whl.
File metadata
- Download URL: discourses-1.0.5-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86f7c1f8c080b4cb898efbe360f0c9468595b720966816179d2447c0b10ef41c
|
|
| MD5 |
e516bd3ad92f4c3a241ff85aa75542ac
|
|
| BLAKE2b-256 |
a7575253940d2ddae335c29472203d575127d7c78b0af2502e1e5918a78d69ff
|