analysis-poly 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- analysis_poly/__init__.py +3 -0
- analysis_poly/analyzer.py +587 -0
- analysis_poly/cli.py +28 -0
- analysis_poly/logging_config.py +29 -0
- analysis_poly/main.py +27 -0
- analysis_poly/market_cache.py +133 -0
- analysis_poly/market_result_cache.py +52 -0
- analysis_poly/models.py +183 -0
- analysis_poly/open_with_params.py +143 -0
- analysis_poly/polymarket_client.py +141 -0
- analysis_poly/profit_engine.py +417 -0
- analysis_poly/run_manager.py +289 -0
- analysis_poly/slugs.py +31 -0
- analysis_poly/static/dist/app.css +1 -0
- analysis_poly/static/dist/app.js +485 -0
- analysis_poly/templates/index.html +17 -0
- analysis_poly/web.py +74 -0
- analysis_poly-0.1.0.dist-info/METADATA +107 -0
- analysis_poly-0.1.0.dist-info/RECORD +22 -0
- analysis_poly-0.1.0.dist-info/WHEEL +5 -0
- analysis_poly-0.1.0.dist-info/entry_points.txt +3 -0
- analysis_poly-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Polypolice Real Profit Dashboard</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
|
|
10
|
+
<link rel="stylesheet" href="/static/dist/app.css?v={{ static_version }}" />
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script id="server-defaults" type="application/json">{{ {"default_address": default_address, "default_symbols": default_symbols, "default_intervals": default_intervals} | tojson }}</script>
|
|
15
|
+
<script type="module" src="/static/dist/app.js?v={{ static_version }}"></script>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
analysis_poly/web.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from fastapi import FastAPI, Request
|
|
7
|
+
from fastapi.responses import HTMLResponse, StreamingResponse
|
|
8
|
+
from fastapi.staticfiles import StaticFiles
|
|
9
|
+
from fastapi.templating import Jinja2Templates
|
|
10
|
+
from loguru import logger
|
|
11
|
+
|
|
12
|
+
from .logging_config import configure_logging
|
|
13
|
+
from .models import AnalysisRequest, RunCreated, RunState, RunStopAck
|
|
14
|
+
from .run_manager import RunManager
|
|
15
|
+
|
|
16
|
+
PACKAGE_DIR = Path(__file__).resolve().parent
|
|
17
|
+
TEMPLATES_DIR = PACKAGE_DIR / "templates"
|
|
18
|
+
STATIC_DIR = PACKAGE_DIR / "static"
|
|
19
|
+
REPORTS_DIR = Path(os.getenv("ANALYSIS_POLY_REPORTS_DIR", "reports")).expanduser().resolve()
|
|
20
|
+
REPORTS_DIR.mkdir(parents=True, exist_ok=True)
|
|
21
|
+
configure_logging()
|
|
22
|
+
|
|
23
|
+
app = FastAPI(title="Polymarket Profit Analyzer")
|
|
24
|
+
templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
|
|
25
|
+
run_manager = RunManager()
|
|
26
|
+
|
|
27
|
+
app.mount("/reports", StaticFiles(directory=str(REPORTS_DIR)), name="reports")
|
|
28
|
+
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@app.get("/", response_class=HTMLResponse)
|
|
32
|
+
async def index(request: Request):
|
|
33
|
+
app_js = STATIC_DIR / "dist" / "app.js"
|
|
34
|
+
app_css = STATIC_DIR / "dist" / "app.css"
|
|
35
|
+
static_version = str(
|
|
36
|
+
int(max(app_js.stat().st_mtime if app_js.exists() else 0, app_css.stat().st_mtime if app_css.exists() else 0))
|
|
37
|
+
)
|
|
38
|
+
return templates.TemplateResponse(
|
|
39
|
+
request=request,
|
|
40
|
+
name="index.html",
|
|
41
|
+
context={
|
|
42
|
+
"default_address": "",
|
|
43
|
+
"default_symbols": "btc,eth,sol,xrp",
|
|
44
|
+
"default_intervals": "5,15",
|
|
45
|
+
"static_version": static_version,
|
|
46
|
+
},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@app.post("/api/runs", response_model=RunCreated)
|
|
51
|
+
async def create_run(req: AnalysisRequest):
|
|
52
|
+
logger.info(f"create run request: {req.model_dump_json(ensure_ascii=False, indent=4)}")
|
|
53
|
+
return await run_manager.create_run(req)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@app.get("/api/runs/{run_id}/stream")
|
|
57
|
+
async def stream_run(run_id: str):
|
|
58
|
+
generator = run_manager.stream(run_id)
|
|
59
|
+
return StreamingResponse(generator, media_type="text/event-stream")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@app.post("/api/runs/{run_id}/stop", response_model=RunStopAck)
|
|
63
|
+
async def stop_run(run_id: str):
|
|
64
|
+
return await run_manager.stop_run(run_id)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@app.get("/api/runs/{run_id}/result")
|
|
68
|
+
async def run_result(run_id: str):
|
|
69
|
+
return await run_manager.get_result(run_id)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@app.get("/api/runs/{run_id}/state", response_model=RunState)
|
|
73
|
+
async def run_state(run_id: str):
|
|
74
|
+
return await run_manager.get_state(run_id)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: analysis-poly
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Polymarket real-profit web analyzer
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastapi>=0.115.0
|
|
8
|
+
Requires-Dist: httpx>=0.28.1
|
|
9
|
+
Requires-Dist: jinja2>=3.1.6
|
|
10
|
+
Requires-Dist: loguru>=0.7.3
|
|
11
|
+
Requires-Dist: pydantic>=2.11.0
|
|
12
|
+
Requires-Dist: uvicorn>=0.35.0
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest>=8.3.4; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
16
|
+
|
|
17
|
+
# analysis-poly
|
|
18
|
+
|
|
19
|
+
**Real Profit (Fee-Excluded View)**
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
中文说明见:[README_zh.md](README_zh.md)
|
|
25
|
+
|
|
26
|
+
Polymarket real-profit analyzer with a web UI.
|
|
27
|
+
|
|
28
|
+
## Scope (Important)
|
|
29
|
+
|
|
30
|
+
- This tool is primarily designed for Polymarket crypto `updown` markets with taker fees, especially `5m` and `15m` intervals.
|
|
31
|
+
- It is **not** intended as a universal PnL engine for all Polymarket market types.
|
|
32
|
+
- Main purpose: quantify and visualize the impact of trading fees on real profitability (`Net PnL` vs `No-Fee PnL`).
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- Python `3.11+` (recommended: `3.11`)
|
|
37
|
+
- `uv` package manager
|
|
38
|
+
|
|
39
|
+
## Install As Package
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv pip install .
|
|
43
|
+
# or
|
|
44
|
+
pip install .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
After install:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
analysis-poly
|
|
51
|
+
analysis-poly-open --address 0xabc --symbols btc,eth --intervals 5,15
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Run
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv sync
|
|
58
|
+
uv run python main.py
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Open [http://localhost:8000](http://localhost:8000).
|
|
62
|
+
|
|
63
|
+
## CLI Open + Auto Start
|
|
64
|
+
|
|
65
|
+
Use a standalone script to start server, open browser, and pass params in URL.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
uv run -m analysis_poly.open_with_params \
|
|
69
|
+
--address 0xabc \
|
|
70
|
+
--symbols btc,eth \
|
|
71
|
+
--intervals 5,15 \
|
|
72
|
+
--start-time "2026-03-01 00:00" \
|
|
73
|
+
--end-time "2026-03-02 00:00" \
|
|
74
|
+
--concurrency 8
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Frontend will read query params, fill form fields, and auto start the run.
|
|
78
|
+
|
|
79
|
+
## First Clone
|
|
80
|
+
|
|
81
|
+
`analysis_poly/static/dist` is committed in the repository, so first startup does not require front-end build.
|
|
82
|
+
|
|
83
|
+
If you modify `frontend/src`, rebuild assets:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install
|
|
87
|
+
npm run build
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## API
|
|
91
|
+
|
|
92
|
+
- `POST /api/runs`
|
|
93
|
+
- `GET /api/runs/{run_id}/stream` (SSE)
|
|
94
|
+
- `POST /api/runs/{run_id}/stop`
|
|
95
|
+
- `GET /api/runs/{run_id}/result`
|
|
96
|
+
- `GET /api/runs/{run_id}/state`
|
|
97
|
+
|
|
98
|
+
## Test
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv run pytest
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Frontend
|
|
105
|
+
|
|
106
|
+
- Source: `frontend/src`
|
|
107
|
+
- Build output: `analysis_poly/static/dist/app.js` and `analysis_poly/static/dist/app.css`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
analysis_poly/__init__.py,sha256=YLcSSU7ik3mx-UfCFDY7dtsNpZ6UYuIHiV8b3kat30M,40
|
|
2
|
+
analysis_poly/analyzer.py,sha256=g3-qS4ihW9vv3vdJaiaghvVTRnnv4m2Qyb7qPikWg7Y,23393
|
|
3
|
+
analysis_poly/cli.py,sha256=2FuB-bfwjQ0mE2zyssrupOymDiHO5TgWADGoGxT9cIc,743
|
|
4
|
+
analysis_poly/logging_config.py,sha256=AcKe54oVeMVGbn4RgPk_cDyNynTs6aZohDscqRWLtYQ,615
|
|
5
|
+
analysis_poly/main.py,sha256=k7f8a2_vi9qO2dxXuuQERn5sRoMD4ZzeeLe9JUzmjDQ,580
|
|
6
|
+
analysis_poly/market_cache.py,sha256=B3hwGRXEO493ASOaO8uk68yLq76Cfx_-sMUp4xhe0eM,4583
|
|
7
|
+
analysis_poly/market_result_cache.py,sha256=w55kCSaHzLU10JpzmfUqkRBylzCf2Y9s_th0h4XD48A,1649
|
|
8
|
+
analysis_poly/models.py,sha256=lIh0luRczcUnC5tPhof1vkEUMvA528-GiOob6wvvM2I,4689
|
|
9
|
+
analysis_poly/open_with_params.py,sha256=kbcmIX_rydzRfryh7Ae5CyiMato0mn5fpn3KEzawAlA,4796
|
|
10
|
+
analysis_poly/polymarket_client.py,sha256=d7em-i6PtOnRdHRCp_w26-XMIfANmcuLeO2ljnlkEHA,4568
|
|
11
|
+
analysis_poly/profit_engine.py,sha256=VzpIgxiX3C64gMDzBykt548xD8Kc4vObem_UwtLpa7c,14316
|
|
12
|
+
analysis_poly/run_manager.py,sha256=UrBnH0-UNcEMYjC02wYsTLKzHElElvQAqJWToHf-l70,10329
|
|
13
|
+
analysis_poly/slugs.py,sha256=3X3wNKR9clTxfgYQC_jrhooitPqwJrAOuiZKP2xTepM,881
|
|
14
|
+
analysis_poly/web.py,sha256=OhBY4K2DAjyk4CrC8-VmmTTmamra-VLgXsXiitEunbA,2473
|
|
15
|
+
analysis_poly/static/dist/app.css,sha256=gLsGy68QoJkQ71gHfQ__wMXaIQlXmpaTKTZ-GSBjPfI,6987
|
|
16
|
+
analysis_poly/static/dist/app.js,sha256=o5-uY1GxYmW5xjEBXtzShWOSC3Qy_ohOmYxk4i8PHQ4,2118678
|
|
17
|
+
analysis_poly/templates/index.html,sha256=FE8CoOQjfXsYFam9oYfv-iyQZil5ZG2Lz1Oh1L10VmE,898
|
|
18
|
+
analysis_poly-0.1.0.dist-info/METADATA,sha256=XsaLvm9n9XC9rz0apTR9J2ytTa4mgOfEjZvg_qDPfZM,2326
|
|
19
|
+
analysis_poly-0.1.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
|
20
|
+
analysis_poly-0.1.0.dist-info/entry_points.txt,sha256=Oi27CFAzPJel-gn4lFxM_2r0D9e-pO7tRgI2nTZ0qUg,114
|
|
21
|
+
analysis_poly-0.1.0.dist-info/top_level.txt,sha256=RU1f2PiIVa5YWtf3pDf8UjMrpzFLTJYBTaikalS48q4,14
|
|
22
|
+
analysis_poly-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
analysis_poly
|