diff --git a/submissions/options_gps_submission.md b/submissions/options_gps_submission.md new file mode 100644 index 0000000..e64ee9d --- /dev/null +++ b/submissions/options_gps_submission.md @@ -0,0 +1,45 @@ +# Options GPS — Best Options Tool Submission + +--- + +## 2. Technical Details (1-page) + +### Architecture Overview + +Options GPS is a Python CLI tool built on a modular pipeline architecture with four layers: + +1. **Data Layer (`SynthClient`)** — Fetches probabilistic forecasts (1h and 24h prediction percentiles), option pricing, and volatility data from the Synth API. The client supports live and mock modes, allowing development without an API key. + +2. **Pipeline Layer (`pipeline.py`)** — The analytical core. It takes user inputs (symbol, view, risk) and executes a multi-stage pipeline: forecast fusion (comparing 1h and 24h medians to determine Aligned/Countermove/Unclear state), strategy generation (building candidates from option strikes per view and risk), payoff and probability computation (CDF-weighted probability of profit and expected value using Synth's percentile distribution), and ranking (scoring strategies by fit-to-view, PoP, expected return, and tail penalty). + +3. **Exchange Layer (`exchange.py`)** — Fetches live quotes from Deribit (JSON-RPC 2.0) and Aevo (REST with HMAC-SHA256). Computes per-leg price divergences between Synth fair value and exchange prices, enabling Market Line Shopping — each leg is routed to the cheapest venue automatically. + +4. **Execution Layer (`executor.py`)** — Builds execution plans, resolves exchange-specific instrument names, and handles the full order lifecycle (place → poll → cancel). Includes slippage protection, partial-failure rollback (auto-cancel filled legs if a later leg fails), and quantity overrides. + +### How Synth API Is Integrated + +The tool consumes three Synth endpoints: +- **`get_prediction_percentiles(asset, horizon)`** — The backbone of the tool. 1h and 24h percentile distributions power both the forecast fusion logic (is 1h aligned with 24h?) and the payoff engine (what is the CDF-weighted probability a given strike finishes in-the-money?). +- **`get_option_pricing(asset)`** — Theoretical call/put prices by strike. Used to build strategy candidates and compute costs. For the vol view, ATM premiums are used to derive implied volatility via the Brenner-Subrahmanyam approximation. +- **`get_volatility(asset, horizon)`** — Forecasted and realized volatility. Feeds the guardrail system (suppress trades when volatility is extreme) and provides the Synth vol signal for IV comparison in vol view. + +### Data Consumption Approach + +Rather than treating Synth data as a simple directional signal, Options GPS decomposes the full 9-percentile distribution into a CDF for probability-weighted payoff analysis. The 1h and 24h forecasts are fused to detect signal alignment or conflict, preventing trades when timeframes disagree. For crypto options, the tool goes further: it cross-references Synth's theoretical fair prices against live Deribit/Aevo quotes, giving strategies a score bonus when exchange prices are cheaper than Synth fair value — surfacing real-time market inefficiencies. + +### Key Insights + +- **Multi-timeframe fusion prevents bad trades.** Fusing 1h and 24h forecasts catches divergent signals before capital is at risk. This is one of the strongest use cases for Synth's multi-horizon data. +- **Full distribution beats point estimates.** Using all 9 percentiles for CDF-weighted PoP/EV produces more accurate risk-reward profiles than relying on a single median forecast. +- **Probabilistic data enables automated line shopping.** Because Synth provides fair value pricing, the tool can objectively compare exchange quotes and route to the best venue per leg — something not possible with directional-only signals. +- **Guardrails build user trust.** By refusing to trade when confidence is low or signals conflict, the tool demonstrates responsible use of probabilistic data and prevents forced trades in uncertain conditions. + +--- + +## 3. What problem does your project solve? + +Options trading is notoriously complex — traders must simultaneously evaluate market direction, choose a strategy, select strikes, and manage risk across multiple exchanges. Most retail traders either over-simplify (buying naked calls) or get paralyzed by the number of choices. Options GPS solves this by converting a simple three-input market view (symbol, direction, risk tolerance) into a fully ranked set of strategy recommendations, complete with probability of profit, expected value, and risk management rules — all driven by Synth's probabilistic forecasts rather than gut feel. For crypto options, it goes even further by automatically comparing prices across Deribit and Aevo and routing each leg to the cheapest venue, then executing the trade end-to-end. + +## 4. What makes your project unique? + +Options GPS is the only tool that fuses multi-timeframe Synth forecasts (1h + 24h) into a single coherent signal, uses the full probabilistic distribution for CDF-weighted payoff analysis, and then closes the loop with autonomous multi-exchange execution. Most options screeners stop at showing greeks or IV rank — Options GPS goes from "I'm bullish on ETH" to a fully executed, multi-leg strategy on the best-priced exchange in a single command. The guardrail system is equally distinctive: rather than blindly trading every signal, the tool explicitly refuses when Synth's own data shows conflicting timeframes, low confidence, or no vol edge, making it a responsible decision engine rather than just a trade executor. diff --git a/submissions/synth_overlay_submission.md b/submissions/synth_overlay_submission.md new file mode 100644 index 0000000..3c7d194 --- /dev/null +++ b/submissions/synth_overlay_submission.md @@ -0,0 +1,45 @@ +# Synth Overlay — Best Prediction Markets Tool Submission + +--- + +## 2. Technical Details (1-page) + +### Architecture Overview + +Synth Overlay is a Chrome extension with a Python backend, following a platform registry architecture that cleanly separates platform-specific logic from the core edge analysis. The system has three layers: + +1. **Python Server (`server.py`, `analyzer.py`, `matcher.py`, `edge.py`)** — A lightweight HTTP server exposing a single edge endpoint (`GET /api/edge?slug=...&platform=...`). The `matcher.py` module implements a platform registry pattern: each platform (Polymarket, Kalshi) is a self-contained entry with its own URL patterns, asset maps, slug normalization, and market-type detection (daily, hourly, 15-min, 5-min, range). The `analyzer.py` `EdgeAnalyzer` fetches Synth data for the matched asset and horizon, computes edge, confidence, signal direction, and invalidation conditions. Adding a new prediction market platform requires adding one registry entry — no scattered if/else logic. + +2. **Chrome Extension (`extension/`)** — Uses Chrome's native Side Panel API (`chrome.sidePanel`) rather than injecting DOM elements. A content script detects the active platform from the hostname, extracts the market slug via platform-specific URL parsing, and scrapes live market prices and wallet balance from the DOM. The side panel page communicates with the content script and the local Python server to render edge data, position sizing, and alerts. + +3. **Alert Engine (`background.js`)** — A service worker using `chrome.alarms` to poll watched markets every 60 seconds. When edge exceeds the user's threshold, a browser notification fires with contextual info (asset, edge, signal, confidence). Notifications have a 5-minute cooldown per market and are suppressed when the user is already viewing the market. + +### How Synth API Is Integrated + +The server consumes multiple Synth prediction market endpoints depending on the detected market type: +- **`get_polymarket_daily/hourly/15min/5min(asset)`** — Returns Synth vs. market Up/Down probabilities at the matched time horizon. This is the primary edge source. +- **`get_polymarket_range()`** — For range-bracket markets, provides Synth vs. market probability per price bracket. +- **`get_prediction_percentiles(asset, horizon)`** — Used by the confidence scoring algorithm; forecast distribution width determines how certain the signal is. + +The edge computation is straightforward: `edge = synth_probability - market_probability`. This raw edge, combined with confidence from the percentile spread, feeds both the signal explanation and the Kelly position sizer. + +### Data Consumption Approach + +The extension follows a "Synth-sourced prices only" principle — it never uses DOM-scraped market prices for the edge calculation, only for displaying what the market currently shows. This avoids sync issues between stale DOM data and fresh Synth data. The confidence score is derived from the width of Synth's percentile distribution: a narrow spread means high confidence (Synth is sure about the outcome), while a wide spread means low confidence. This confidence directly scales the Kelly fraction, preventing large bets on uncertain signals. + +### Key Insights + +- **The prediction market use case is uniquely well-suited to Synth.** Binary outcome markets have a natural probability interpretation, and Synth's probabilistic forecasts map directly to "fair" YES/NO prices — making edge computation both rigorous and intuitive. +- **Kelly sizing with confidence scaling is the responsible edge.** Raw Kelly sizing can be aggressive; scaling by Synth's confidence score and capping at 20% of bankroll makes the sizing recommendations practical and robust to forecast noise. +- **Platform registry pattern enables rapid expansion.** The clean separation of platform-specific logic means supporting new prediction market platforms (e.g. Manifold, Metaculus) is a single-file addition. +- **Native Side Panel > DOM injection.** Using Chrome's Side Panel API avoids UI breakage when Polymarket/Kalshi updates their frontend, and provides a cleaner user experience. + +--- + +## 3. What problem does your project solve? + +Prediction market traders on Polymarket and Kalshi have no easy way to compare market-implied probabilities against independent probabilistic forecasts — they're trading on gut feel, news sentiment, or stale analysis. Synth Overlay solves this by surfacing the exact numerical edge between Synth's forecasts and market prices directly in the browser as the user browses markets. It goes beyond showing the edge by answering the critical follow-up question: "how much should I bet?" — using Kelly-optimal position sizing scaled by forecast confidence and the user's actual wallet balance, preventing both over-betting on weak signals and under-betting on strong ones. + +## 4. What makes your project unique? + +Synth Overlay is the only tool that embeds probabilistic forecast edge directly into the prediction market browsing experience via Chrome's native Side Panel — no separate dashboard, no copy-pasting slugs, no context switching. The combination of real-time edge computation, confidence-aware Kelly position sizing, multi-platform support (Polymarket + Kalshi), and a background alert engine that notifies traders when edge exceeds their threshold creates a complete edge-detection-to-sizing workflow that doesn't exist anywhere else. The platform registry architecture also makes it trivially extensible — adding a new prediction market platform is a single registry entry on each side (Python server + JS extension), not a codebase-wide refactor. diff --git a/submissions/tide_chart_submission.md b/submissions/tide_chart_submission.md new file mode 100644 index 0000000..cc1fa63 --- /dev/null +++ b/submissions/tide_chart_submission.md @@ -0,0 +1,42 @@ +# Tide Chart — Best Equities Application Submission + +--- + +## 2. Technical Details (1-page) + +### Architecture Overview + +Tide Chart is a Flask web application with three integrated subsystems: + +1. **Forecast Engine (`main.py`, `chart.py`)** — Fetches Synth prediction percentiles and volatility for all supported assets, normalizes raw price forecasts to percentage change (`(percentile - current_price) / current_price × 100`), and computes ranked metrics from the final time step: median move, upside (95th), downside (5th), directional skew, range, and relative-to-benchmark performance (SPY for equities, BTC for crypto). The chart module generates interactive Plotly probability cone traces with 5th-95th percentile bands. A probability calculator uses linear interpolation across 9 percentile levels to estimate P(price ≤ target) for any user-supplied price. + +2. **Trading Engine (`gtrade.py`)** — Integrates with gTrade (Gains Network) v9 on Arbitrum One for leveraged DeFi trading. Handles pair resolution (mapping Synth tickers to gTrade pair indices via the Gains Network backend API), server-side trade validation with per-group protocol limits (leverage ranges, collateral bounds, $1,500 minimum position size), USDC allowance checking, and `openTrade` transaction construction targeting the Diamond proxy contract. Protocol guards are enforced both client-side (Execute button disabled with reason label) and server-side (validation endpoint mirrors the same rules). + +3. **Frontend (`static/`)** — Single-page dashboard using Plotly.js (CDN) for interactive charting and ethers.js v6 (CDN) for wallet connection and transaction signing. The frontend handles MetaMask connection, automatic chain switching to Arbitrum One (chain ID 42161), USDC balance display, trade form with live preview, and toast notifications for transaction status. Auto-refresh polls updated forecast data every 5 minutes. + +### How Synth API Is Integrated + +The dashboard consumes two core Synth endpoints: +- **`get_prediction_percentiles(asset, horizon)`** — The primary data source. Provides time-step probabilistic forecasts with 9 percentile levels (0.5% to 99.5%). Powers the probability cone visualization, the ranked metrics table, and the probability calculator. Each asset's forecast is independently fetched and normalized for cross-asset comparison. +- **`get_volatility(asset, horizon)`** — Provides forecasted average volatility. Displayed as an independent risk measure in the rankings table alongside directional metrics. + +### Data Consumption Approach + +Tide Chart's key innovation is normalization: all assets are converted from absolute price levels to percentage change so that a $90,000 BTC forecast can be directly compared against a $600 SPY forecast in the same chart and table. Metrics are computed at the terminal time step of the forecast window, and each asset's performance is benchmarked against a category reference (SPY for equities, BTC for crypto), surfacing relative outperformance or underperformance. The probability calculator goes further — it interpolates across Synth's 9 percentile levels to provide a point estimate of the probability of reaching any user-specified price, turning the distribution curve into an actionable answer. + +### Key Insights + +- **Cross-asset comparison is a killer feature for equities.** Normalizing to percentage change lets traders instantly see which equity has the strongest Synth forecast outlook — something that's impossible when looking at raw price levels. +- **Forecast-to-execution in one click bridges the intelligence gap.** Most forecast tools show data and leave execution to the user. Tide Chart closes the loop: see the probability cone → check the ranked metrics → execute a leveraged trade on gTrade, all without leaving the dashboard. +- **Protocol guards prevent user errors.** By enforcing gTrade's leverage, collateral, and position size rules both client-side and server-side, the tool prevents rejected transactions and wasted gas fees. +- **Probabilistic data is more useful as a distribution than a point estimate.** The probability calculator demonstrates this — instead of just showing "median up 1.2%", the user can ask "what's the probability of reaching my specific target?" and get a numerically rigorous answer. + +--- + +## 3. What problem does your project solve? + +Retail traders interested in equities and crypto lack a tool that combines probabilistic forecasts with actionable comparison metrics and direct trade execution in one interface. Existing charting tools show historical data but no forward-looking probability distributions; existing DeFi frontends let you trade but provide no forecast intelligence. Tide Chart bridges this gap by normalizing Synth's probabilistic forecasts across all supported assets (equities, crypto, gold) into a single ranked view with interactive probability cones, a probability calculator for custom price targets, and a direct on-chain trading interface on Arbitrum via gTrade — from forecast insight to leveraged position in one seamless workflow. + +## 4. What makes your project unique? + +Tide Chart is the only tool that normalizes Synth's multi-asset probabilistic forecasts into a single cross-asset comparison dashboard and then lets users act on those forecasts by executing leveraged trades on-chain via gTrade, all within the same interface. The combination of visual probability cones, a ranked metrics table with relative benchmarking (vs. SPY or BTC), a probability calculator that interpolates across Synth's full percentile distribution, and integrated DeFi execution with protocol-level safety guards creates a workflow that doesn't exist elsewhere. It's not just a chart or just a trading terminal — it's the complete loop from "which asset has the best forecast?" to "I now have a leveraged position open," powered entirely by Synth's probabilistic data. diff --git a/synth_client/client.py b/synth_client/client.py index 7954178..1a42a18 100644 --- a/synth_client/client.py +++ b/synth_client/client.py @@ -50,6 +50,7 @@ def __init__(self, api_key: str | None = None, mock_data_dir: str | None = None) """ self.api_key = api_key or os.environ.get("SYNTH_API_KEY") self.mock_mode = self.api_key is None + self.session = requests.Session() if _HAS_REQUESTS else None if self.mock_mode: warnings.warn( @@ -77,7 +78,7 @@ def _request(self, path: str, params: dict | None = None) -> dict | list: ) headers = {"Authorization": f"Apikey {self.api_key}"} - resp = requests.get(f"{BASE_URL}{path}", headers=headers, params=params, timeout=30) + resp = self.session.get(f"{BASE_URL}{path}", headers=headers, params=params, timeout=5) resp.raise_for_status() return resp.json() @@ -105,7 +106,14 @@ def _get(self, path: str, mock_path_parts: list[str], params: dict | None = None """ if self.mock_mode: return self._load_mock(*mock_path_parts) - return self._request(path, params) + try: + return self._request(path, params) + except requests.exceptions.RequestException as e: + warnings.warn(f"Live API failed for {path} with params {params}: {e}. Falling back to mock data.", stacklevel=2) + try: + return self._load_mock(*mock_path_parts) + except Exception as mock_err: + raise RuntimeError(f"Live API failed AND mock data unavailable: {e}") from mock_err # ─── Prediction Percentiles ────────────────────────────────────── diff --git a/tools/synth-overlay/server.py b/tools/synth-overlay/server.py index 6f643bc..cf6d314 100644 --- a/tools/synth-overlay/server.py +++ b/tools/synth-overlay/server.py @@ -12,6 +12,14 @@ sys.path.insert(0, _here) from flask import Flask, jsonify, request +import os +import sys + +from dotenv import load_dotenv + +_here = os.path.dirname(os.path.abspath(__file__)) +env_path = os.path.join(_here, "../../.env") +load_dotenv(env_path) from synth_client import SynthClient diff --git a/tools/tide-chart/chart.py b/tools/tide-chart/chart.py index 3f03362..cf81887 100644 --- a/tools/tide-chart/chart.py +++ b/tools/tide-chart/chart.py @@ -42,11 +42,17 @@ def fetch_all_data(client, horizon: str = "24h") -> dict: Returns: dict: {asset: {"percentiles": ..., "volatility": ..., "current_price": float}} """ + import time assets = get_assets_for_horizon(horizon) data = {} - for asset in assets: + for i, asset in enumerate(assets): + print(f"Fetching percentiles for {asset}...", flush=True) forecast = client.get_prediction_percentiles(asset, horizon=horizon) + time.sleep(1.0) + print(f"Fetching volatility for {asset}...", flush=True) vol = client.get_volatility(asset, horizon=horizon) + time.sleep(1.0) + print(f"Done fetching {asset}.", flush=True) data[asset] = { "current_price": forecast["current_price"], "percentiles": forecast["forecast_future"]["percentiles"], diff --git a/tools/tide-chart/main.py b/tools/tide-chart/main.py index 84b518e..653ecd8 100644 --- a/tools/tide-chart/main.py +++ b/tools/tide-chart/main.py @@ -1,5 +1,8 @@ import sys import os +from dotenv import load_dotenv + +load_dotenv(os.path.join(os.path.dirname(__file__), "../../.env")) sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../..")) diff --git a/tools/tide-chart/requirements.txt b/tools/tide-chart/requirements.txt index 0f8f77b..9869211 100644 --- a/tools/tide-chart/requirements.txt +++ b/tools/tide-chart/requirements.txt @@ -1,3 +1,4 @@ plotly>=5.0.0 requests>=2.28.0 flask>=3.0.0 +python-dotenv>=1.0.0 diff --git a/tools/tide-chart/static/trading.js b/tools/tide-chart/static/trading.js index 1a3720e..534d018 100644 --- a/tools/tide-chart/static/trading.js +++ b/tools/tide-chart/static/trading.js @@ -43,6 +43,10 @@ function getTradeHistory() { } function saveTradeToHistory(entry) { + if (entry.lev === '0x' || entry.lev === '?x') return; + if (!entry.collateral || parseFloat(entry.collateral) <= 0) return; + if (!entry.entryPrice || parseFloat(entry.entryPrice) <= 0) return; + var history = getTradeHistory(); history.unshift(entry); if (history.length > 50) history = history.slice(0, 50); @@ -1259,7 +1263,13 @@ async function loadTradeHistory() { } }); - // Limit to 20 most recent + // Filter out invalid/zeroed-out trades and limit to 20 most recent + merged = merged.filter(function(h) { + if (h.lev === '0x' || h.lev === '?x') return false; + if (!h.collateral || parseFloat(h.collateral) <= 0) return false; + if (!h.entryPrice || parseFloat(h.entryPrice) <= 0) return false; + return true; + }); merged = merged.slice(0, 20); if (merged.length === 0) {