Aliazimi00 commited on
Commit
67ffbc4
·
verified ·
1 Parent(s): 1af87ec

Add Jared read-only token OHLCV ingestion and manual contract lookup

Browse files
Files changed (1) hide show
  1. core/data.py +132 -0
core/data.py CHANGED
@@ -81,6 +81,127 @@ def fetch_ompfinex_data(ticker, start_date, end_date, interval):
81
  print_log(f"OMPFINEX fetch failed for {ticker}: {str(e)}", 'ERROR')
82
  return pd.DataFrame()
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  def load_data(data_src='yahoo', ticker='AAPL', start='2020-01-01', end='2023-01-01', interval='1d', file_upload=None, alpha_api_key=None):
85
  try:
86
  print_log(f"Loading data: source={data_src}, ticker={ticker}, start={start}, end={end}, interval={interval}, file_upload={'set' if file_upload else 'unset'}, alpha_api_key={'set' if alpha_api_key else 'unset'}")
@@ -115,6 +236,17 @@ def load_data(data_src='yahoo', ticker='AAPL', start='2020-01-01', end='2023-01-
115
  except Exception as e:
116
  print_log(f"Failed to load CSV {file_path}: {str(e)}", 'ERROR')
117
  raise ValueError(f"Failed to load CSV: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
118
  elif ticker in ["USDT-IRT", "BTC-IRT", "ETH-IRT"]:
119
  print_log(f"Fetching {ticker} from OMPFINEX")
120
  df = fetch_ompfinex_data(ticker, start_date, end_date, interval)
 
81
  print_log(f"OMPFINEX fetch failed for {ticker}: {str(e)}", 'ERROR')
82
  return pd.DataFrame()
83
 
84
+ JARED_TRPC_BASE = os.getenv("JARED_TRPC_BASE", "https://jaredfromsubway.manus.space/api/trpc")
85
+ GECKO_BASE = os.getenv("GECKO_TERMINAL_BASE", "https://api.geckoterminal.com/api/v2")
86
+
87
+
88
+ def _trpc_get(procedure, payload=None, timeout=20):
89
+ """Read-only request to the public Jared evidence console tRPC API."""
90
+ query = {"json": payload}
91
+ response = requests.get(
92
+ f"{JARED_TRPC_BASE.rstrip('/')}/{procedure}",
93
+ params={"input": json.dumps(query, separators=(",", ":"))},
94
+ headers={"accept": "application/json"},
95
+ timeout=timeout,
96
+ )
97
+ response.raise_for_status()
98
+ body = response.json()
99
+ return body.get("result", {}).get("data", {}).get("json")
100
+
101
+
102
+ def fetch_jared_observed_tokens(limit=100):
103
+ """Return source-labeled, read-only wallet observations from Jared's public console."""
104
+ try:
105
+ result = _trpc_get("ml.getObservedTokenTable", {"limit": int(limit)})
106
+ return result if isinstance(result, list) else []
107
+ except Exception as exc:
108
+ print_log(f"Jared observed-token feed unavailable: {exc}", "WARNING")
109
+ return []
110
+
111
+
112
+ def resolve_jared_token(token_query=None):
113
+ """Resolve a symbol/name/address against the public observed-token table.
114
+
115
+ If no query is provided, choose the first observation with a verified OHLCV price.
116
+ The returned metadata is retained by callers for provenance display.
117
+ """
118
+ observations = fetch_jared_observed_tokens()
119
+ query = (token_query or "").strip().lower()
120
+ candidates = observations
121
+ if query:
122
+ candidates = [
123
+ row for row in observations
124
+ if query in str(row.get("tokenAddress", "")).lower()
125
+ or query == str(row.get("symbol", "")).lower()
126
+ or query == str(row.get("name", "")).lower()
127
+ ]
128
+ for row in candidates:
129
+ address = str(row.get("tokenAddress", "")).strip()
130
+ if address.startswith("0x") and len(address) == 42 and (
131
+ row.get("pricePathStatus") == "verified_ohlcv" or row.get("priceUsd") is not None
132
+ ):
133
+ return row
134
+ return None
135
+
136
+
137
+ def _gecko_interval(interval):
138
+ if interval in {"1m", "2m", "5m", "15m", "30m", "60m", "90m", "1h"}:
139
+ return "hour", 1
140
+ if interval in {"1wk"}:
141
+ return "day", 7
142
+ return "day", 1
143
+
144
+
145
+ def fetch_token_ohlcv(address, start_date, end_date, interval="1d", network="eth"):
146
+ """Fetch public DEX OHLCV candles for an ERC-20 address via GeckoTerminal."""
147
+ if not (isinstance(address, str) and address.lower().startswith("0x") and len(address) == 42):
148
+ raise ValueError("A valid EVM token contract address is required")
149
+ headers = {"accept": "application/json"}
150
+ pools_url = f"{GECKO_BASE}/networks/{network}/tokens/{address}/pools"
151
+ pools_resp = requests.get(pools_url, params={"page": 1}, headers=headers, timeout=25)
152
+ pools_resp.raise_for_status()
153
+ pools = pools_resp.json().get("data", [])
154
+ if not pools:
155
+ raise ValueError(f"No public DEX pool found for {address}")
156
+ # Prefer the pool with the greatest 24h USD volume; otherwise use the first pool.
157
+ def volume(pool):
158
+ try:
159
+ return float((pool.get("attributes") or {}).get("volume_usd", {}).get("h24") or 0)
160
+ except Exception:
161
+ return 0.0
162
+ pool = max(pools, key=volume)
163
+ attrs = pool.get("attributes") or {}
164
+ pool_address = attrs.get("address") or str(pool.get("id", "")).split("_", 1)[-1]
165
+ timeframe, aggregate = _gecko_interval(interval)
166
+ ohlcv_url = f"{GECKO_BASE}/networks/{network}/pools/{pool_address}/ohlcv/{timeframe}"
167
+ ohlcv_resp = requests.get(
168
+ ohlcv_url,
169
+ params={"aggregate": aggregate, "limit": 1000},
170
+ headers=headers,
171
+ timeout=25,
172
+ )
173
+ ohlcv_resp.raise_for_status()
174
+ values = (((ohlcv_resp.json().get("data") or {}).get("attributes") or {}).get("ohlcv_list") or [])
175
+ if not values:
176
+ raise ValueError(f"No OHLCV history returned for {address}")
177
+ rows = []
178
+ for candle in values:
179
+ if len(candle) < 6:
180
+ continue
181
+ rows.append({"Date": pd.to_datetime(candle[0], unit="s"), "Open": candle[1], "High": candle[2], "Low": candle[3], "value": candle[4], "Volume": candle[5]})
182
+ df = pd.DataFrame(rows).dropna(subset=["Date", "value"])
183
+ if df.empty:
184
+ raise ValueError(f"OHLCV history contained no usable rows for {address}")
185
+ df = df.set_index("Date").sort_index()
186
+ start_ts, end_ts = pd.to_datetime(start_date), pd.to_datetime(end_date)
187
+ filtered = df[(df.index >= start_ts) & (df.index <= end_ts)]
188
+ # New meme tokens may have only a short history; never fabricate older candles.
189
+ return filtered if not filtered.empty else df
190
+
191
+
192
+ def fetch_jared_token_data(token_query, start_date, end_date, interval="1d"):
193
+ """Resolve a Jared-observed token and load its public DEX OHLCV history."""
194
+ row = resolve_jared_token(token_query)
195
+ if not row:
196
+ raise ValueError("No Jared observation with verified public OHLCV was found; enter a contract address or symbol.")
197
+ df = fetch_token_ohlcv(row["tokenAddress"], start_date, end_date, interval)
198
+ df.attrs["source"] = "Jared public observed-token table + GeckoTerminal public DEX OHLCV"
199
+ df.attrs["token_address"] = row.get("tokenAddress")
200
+ df.attrs["token_symbol"] = row.get("symbol") or row.get("name") or token_query
201
+ df.attrs["jared_observation"] = row
202
+ return df
203
+
204
+
205
  def load_data(data_src='yahoo', ticker='AAPL', start='2020-01-01', end='2023-01-01', interval='1d', file_upload=None, alpha_api_key=None):
206
  try:
207
  print_log(f"Loading data: source={data_src}, ticker={ticker}, start={start}, end={end}, interval={interval}, file_upload={'set' if file_upload else 'unset'}, alpha_api_key={'set' if alpha_api_key else 'unset'}")
 
236
  except Exception as e:
237
  print_log(f"Failed to load CSV {file_path}: {str(e)}", 'ERROR')
238
  raise ValueError(f"Failed to load CSV: {str(e)}")
239
+ elif data_src == 'jared' or ticker == 'JARED-LATEST' or (isinstance(ticker, str) and ticker.lower().startswith('0x')):
240
+ print_log(f"Fetching Jared-observed token OHLCV for {ticker}")
241
+ if isinstance(ticker, str) and ticker.lower().startswith('0x'):
242
+ df = fetch_token_ohlcv(ticker, start_date, end_date, interval)
243
+ df.attrs['source'] = 'Manual EVM contract address + GeckoTerminal public DEX OHLCV'
244
+ df.attrs['token_address'] = ticker
245
+ df.attrs['token_symbol'] = ticker
246
+ else:
247
+ df = fetch_jared_token_data(None if ticker == 'JARED-LATEST' else ticker, start_date, end_date, interval)
248
+ if df.empty:
249
+ raise ValueError(f"No public OHLCV history found for {ticker}")
250
  elif ticker in ["USDT-IRT", "BTC-IRT", "ETH-IRT"]:
251
  print_log(f"Fetching {ticker} from OMPFINEX")
252
  df = fetch_ompfinex_data(ticker, start_date, end_date, interval)