-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathresearch_client.py
More file actions
116 lines (95 loc) · 4.78 KB
/
research_client.py
File metadata and controls
116 lines (95 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""
Simple Octagon Deep Research API client using OpenAI SDK.
"""
import openai
import json
from typing import Dict, Any, Optional, List
from loguru import logger
from config import OctagonConfig
class OctagonClient:
"""Simple client for Octagon Deep Research API using OpenAI SDK."""
def __init__(self, config: OctagonConfig):
self.config = config
self.client = openai.AsyncOpenAI(
api_key=config.api_key,
base_url=config.base_url,
timeout=1800.0 # 30 minutes timeout for deep research
)
async def research_event(self, event: Dict[str, Any], markets: List[Dict[str, Any]]) -> str:
"""
Research an event and its markets using Octagon Deep Research.
Args:
event: Event information (title, subtitle, category, etc.)
markets: List of markets within the event (without odds)
Returns:
Research response as a string
"""
try:
# Format the event and markets for analysis
event_info = f"""
Event: {event.get('title', '')}
Subtitle: {event.get('subtitle', '')}
Mutually Exclusive: {event.get('mutually_exclusive', False)}
"""
markets_info = "Markets:\n"
for i, market in enumerate(markets, 1):
if market.get('volume') < 1000:
continue
# Emphasize human readable title over ticker
title = market.get('title', '')
ticker = market.get('ticker', '')
markets_info += f"{i}. {title}"
if ticker:
markets_info += f" (Ticker: {ticker})"
markets_info += "\n"
if market.get('subtitle'):
markets_info += f" Subtitle: {market.get('subtitle', '')}\n"
markets_info += f" Open: {market.get('open_time', '')}\n"
markets_info += f" Close: {market.get('close_time', '')}\n\n"
prompt = f"""
You are a prediction market expert. Research this event and predict the probability for each market independently.
{event_info}
{markets_info}
Please provide:
1. Overall event analysis and key factors
2. Current sentiment and news analysis
3. For each market, predict the probability of YES outcome (0-100%)
4. Confidence level for each prediction (1-10)
5. Key risks and catalysts that could affect outcomes
6. Trading recommendations for each market
Focus on:
- Independent analysis of each market's probability
- If mutually exclusive: probabilities should sum to ~100% (only one outcome can be true)
- If not mutually exclusive: each market can be evaluated independently
- Provide actionable insights for trading decisions
- Be specific about probability estimates
IMPORTANT: When providing probability predictions, include both the market ticker AND the probability percentage.
Example format: "KXTHEOPEN-25-DMCC: 15%" or "McCarthy (KXTHEOPEN-25-DMCC): 15% probability"
Format your response clearly with market tickers and probability predictions.
"""
event_ticker = event.get('event_ticker', 'UNKNOWN')
logger.info(f"Starting deep research for event {event_ticker} (this may take several minutes)...")
# Use Responses API to handle models that may return reasoning + message
response = await self.client.responses.create(
model="octagon-deep-research-agent",
input=[{"role": "user", "content": prompt}],
reasoning={"effort": "low"},
text={"verbosity": "medium"}
)
logger.info(f"Completed deep research for event {event_ticker}")
# Extract the completed assistant message content safely
try:
from openai_utils import extract_completed_message_text
content_text = extract_completed_message_text(response)
if content_text:
return content_text
except Exception:
pass
# Fallback: return empty string if nothing could be extracted
return ""
except Exception as e:
logger.error(f"Error researching event {event.get('event_ticker', '')}: {e}")
return f"Error researching event: {str(e)}"
async def close(self):
"""Close the client (OpenAI client doesn't need explicit closing)."""
pass