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.
@@ -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
+ ![PnL](assets/pnl.png)
22
+ ![Ratio](assets/ratio.png)
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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ analysis-poly = analysis_poly.cli:main
3
+ analysis-poly-open = analysis_poly.open_with_params:main
@@ -0,0 +1 @@
1
+ analysis_poly