poly-position-watcher 0.2.8__tar.gz → 0.2.9__tar.gz
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.
- {poly_position_watcher-0.2.8/poly_position_watcher.egg-info → poly_position_watcher-0.2.9}/PKG-INFO +11 -2
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/README.md +10 -1
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/_version.py +1 -1
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/position_service.py +2 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/position_model.py +4 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/trade_calculator.py +21 -5
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9/poly_position_watcher.egg-info}/PKG-INFO +11 -2
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/pyproject.toml +1 -1
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/setup.py +1 -1
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/LICENSE +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/MANIFEST.in +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/__init__.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/api_worker.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/__init__.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/enums.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/logger.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/__init__.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/base.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/common_model.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/wss_worker.py +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/SOURCES.txt +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/dependency_links.txt +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/requires.txt +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/top_level.txt +0 -0
- {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/setup.cfg +0 -0
{poly_position_watcher-0.2.8/poly_position_watcher.egg-info → poly_position_watcher-0.2.9}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: poly-position-watcher
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: polymarket proxy wallet redeem
|
|
5
5
|
Home-page: https://github.com/tosmart01/polymarket-position-watcher
|
|
6
6
|
Author: pinbar
|
|
@@ -32,7 +32,8 @@ Dynamic: requires-python
|
|
|
32
32
|
- WSS real-time tracking for `TRADE` and `ORDER` (positions + orders)
|
|
33
33
|
- HTTP polling fallback for reliability
|
|
34
34
|
- Optional fee calculation (toggle + custom formula)
|
|
35
|
-
-
|
|
35
|
+
- Position fields for fill checks:
|
|
36
|
+
`size` (post-fee net size), `original_size` (pre-fee net size), `sellable_size` (on-chain confirmed size), `fee_amount` (accumulated fee amount)
|
|
36
37
|
- Failed trades are detected and returned on positions (`has_failed`, `failed_trades`)
|
|
37
38
|
|
|
38
39
|
**Note: WSS disconnects are auto-detected and reconnected.**
|
|
@@ -71,6 +72,10 @@ with PositionWatcherService(
|
|
|
71
72
|
order: OrderMessage = service.get_order("<order_id>")
|
|
72
73
|
print(position)
|
|
73
74
|
print(order)
|
|
75
|
+
if position:
|
|
76
|
+
print("size(post-fee):", position.size)
|
|
77
|
+
print("size(pre-fee):", position.original_size)
|
|
78
|
+
print("fee_amount:", position.fee_amount)
|
|
74
79
|
service.show_positions(limit=10)
|
|
75
80
|
service.show_orders(limit=10)
|
|
76
81
|
|
|
@@ -113,7 +118,9 @@ OrderMessage(
|
|
|
113
118
|
UserPosition(
|
|
114
119
|
price: 0.0,
|
|
115
120
|
size: 0.0,
|
|
121
|
+
original_size: 0.0,
|
|
116
122
|
volume: 0.0,
|
|
123
|
+
fee_amount: 0.0,
|
|
117
124
|
sellable_size: 0.0,
|
|
118
125
|
token_id: '',
|
|
119
126
|
last_update: 0.0,
|
|
@@ -145,6 +152,8 @@ Some Polymarket markets enable taker fee / maker rebate. This library **fully su
|
|
|
145
152
|
- Enable with `enable_fee_calc=True` to apply fees using `feeRateBps` from trades/orders
|
|
146
153
|
- Customize with `fee_calc_fn` if you need a different formula
|
|
147
154
|
- Disable (default) if you prefer pre-fee positions
|
|
155
|
+
- Returned position fields:
|
|
156
|
+
`size` = post-fee net size, `original_size` = pre-fee net size, `fee_amount` = accumulated fee amount
|
|
148
157
|
|
|
149
158
|
Default fee formula (when `fee_calc_fn` is not provided):
|
|
150
159
|
`fee = 0.25 * (p * (1 - p)) ** 2 * (fee_rate_bps / 1000)`, and `new_size = (1 - fee) * size`.
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
- WSS real-time tracking for `TRADE` and `ORDER` (positions + orders)
|
|
14
14
|
- HTTP polling fallback for reliability
|
|
15
15
|
- Optional fee calculation (toggle + custom formula)
|
|
16
|
-
-
|
|
16
|
+
- Position fields for fill checks:
|
|
17
|
+
`size` (post-fee net size), `original_size` (pre-fee net size), `sellable_size` (on-chain confirmed size), `fee_amount` (accumulated fee amount)
|
|
17
18
|
- Failed trades are detected and returned on positions (`has_failed`, `failed_trades`)
|
|
18
19
|
|
|
19
20
|
**Note: WSS disconnects are auto-detected and reconnected.**
|
|
@@ -52,6 +53,10 @@ with PositionWatcherService(
|
|
|
52
53
|
order: OrderMessage = service.get_order("<order_id>")
|
|
53
54
|
print(position)
|
|
54
55
|
print(order)
|
|
56
|
+
if position:
|
|
57
|
+
print("size(post-fee):", position.size)
|
|
58
|
+
print("size(pre-fee):", position.original_size)
|
|
59
|
+
print("fee_amount:", position.fee_amount)
|
|
55
60
|
service.show_positions(limit=10)
|
|
56
61
|
service.show_orders(limit=10)
|
|
57
62
|
|
|
@@ -94,7 +99,9 @@ OrderMessage(
|
|
|
94
99
|
UserPosition(
|
|
95
100
|
price: 0.0,
|
|
96
101
|
size: 0.0,
|
|
102
|
+
original_size: 0.0,
|
|
97
103
|
volume: 0.0,
|
|
104
|
+
fee_amount: 0.0,
|
|
98
105
|
sellable_size: 0.0,
|
|
99
106
|
token_id: '',
|
|
100
107
|
last_update: 0.0,
|
|
@@ -126,6 +133,8 @@ Some Polymarket markets enable taker fee / maker rebate. This library **fully su
|
|
|
126
133
|
- Enable with `enable_fee_calc=True` to apply fees using `feeRateBps` from trades/orders
|
|
127
134
|
- Customize with `fee_calc_fn` if you need a different formula
|
|
128
135
|
- Disable (default) if you prefer pre-fee positions
|
|
136
|
+
- Returned position fields:
|
|
137
|
+
`size` = post-fee net size, `original_size` = pre-fee net size, `fee_amount` = accumulated fee amount
|
|
129
138
|
|
|
130
139
|
Default fee formula (when `fee_calc_fn` is not provided):
|
|
131
140
|
`fee = 0.25 * (p * (1 - p)) ** 2 * (fee_rate_bps / 1000)`, and `new_size = (1 - fee) * size`.
|
|
@@ -170,7 +170,9 @@ class PositionStore:
|
|
|
170
170
|
current = UserPosition(
|
|
171
171
|
price=position_result.avg_price,
|
|
172
172
|
size=position_result.size,
|
|
173
|
+
original_size=position_result.original_size,
|
|
173
174
|
volume=position_result.amount,
|
|
175
|
+
fee_amount=position_result.fee_amount,
|
|
174
176
|
sellable_size=sellable_size,
|
|
175
177
|
token_id=token_id,
|
|
176
178
|
last_update=position_result.last_update,
|
|
@@ -122,7 +122,9 @@ class OrderMessage(PrettyPrintBaseModel):
|
|
|
122
122
|
class UserPosition(PrettyPrintBaseModel):
|
|
123
123
|
price: float
|
|
124
124
|
size: float
|
|
125
|
+
original_size: float = 0.0
|
|
125
126
|
volume: float
|
|
127
|
+
fee_amount: float = 0.0
|
|
126
128
|
sellable_size: float = 0.0
|
|
127
129
|
token_id: Optional[str] = None
|
|
128
130
|
last_update: float
|
|
@@ -150,9 +152,11 @@ class PositionResult(PrettyPrintBaseModel):
|
|
|
150
152
|
"""仓位计算结果"""
|
|
151
153
|
|
|
152
154
|
size: float
|
|
155
|
+
original_size: float = 0.0
|
|
153
156
|
avg_price: float
|
|
154
157
|
realized_pnl: float
|
|
155
158
|
amount: float
|
|
159
|
+
fee_amount: float = 0.0
|
|
156
160
|
position_value: Optional[float] = None
|
|
157
161
|
unrealized_pnl: Optional[float] = None
|
|
158
162
|
total_pnl: Optional[float] = None
|
|
@@ -39,18 +39,23 @@ def calculate_position_from_trades(
|
|
|
39
39
|
|
|
40
40
|
buy_events = []
|
|
41
41
|
sell_events = []
|
|
42
|
+
total_original_size = 0.0
|
|
42
43
|
|
|
43
44
|
def apply_fee(
|
|
44
45
|
size: float, price: float, fee_rate_bps: float, trader_side: str | None
|
|
45
|
-
) -> float:
|
|
46
|
+
) -> tuple[float, float]:
|
|
46
47
|
if (
|
|
47
48
|
not enable_fee_calc
|
|
48
49
|
or fee_rate_bps <= 0
|
|
49
50
|
or trader_side != "TAKER"
|
|
50
51
|
):
|
|
51
|
-
return size
|
|
52
|
+
return size, 0.0
|
|
52
53
|
calc = fee_calc_fn or _default_fee_calc
|
|
53
|
-
|
|
54
|
+
size_after_fee = calc(size, price, fee_rate_bps)
|
|
55
|
+
fee_amount = (size - size_after_fee) * price
|
|
56
|
+
return size_after_fee, fee_amount
|
|
57
|
+
|
|
58
|
+
total_fee_amount = 0.0
|
|
54
59
|
|
|
55
60
|
# --- 1. 解析所有交易 ---
|
|
56
61
|
for trade in trades:
|
|
@@ -61,24 +66,30 @@ def calculate_position_from_trades(
|
|
|
61
66
|
if order.maker_address.upper() != user_address.upper():
|
|
62
67
|
continue
|
|
63
68
|
is_maker_order = True
|
|
64
|
-
size = apply_fee(
|
|
69
|
+
size, fee_amount = apply_fee(
|
|
65
70
|
order.size, order.price, order.fee_rate_bps, trade.trader_side
|
|
66
71
|
)
|
|
72
|
+
total_fee_amount += fee_amount
|
|
67
73
|
|
|
68
74
|
if order.side == Side.BUY:
|
|
69
75
|
buy_events.append((size, order.price, trade.match_time))
|
|
76
|
+
total_original_size += order.size
|
|
70
77
|
else:
|
|
71
78
|
sell_events.append((-size, order.price, trade.match_time))
|
|
79
|
+
total_original_size -= order.size
|
|
72
80
|
|
|
73
81
|
# taker 部分
|
|
74
82
|
if not is_maker_order and trade.maker_address.upper() == user_address.upper():
|
|
75
|
-
size = apply_fee(
|
|
83
|
+
size, fee_amount = apply_fee(
|
|
76
84
|
trade.size, trade.price, trade.fee_rate_bps, trade.trader_side
|
|
77
85
|
)
|
|
86
|
+
total_fee_amount += fee_amount
|
|
78
87
|
if trade.side == Side.BUY:
|
|
79
88
|
buy_events.append((size, trade.price, trade.match_time))
|
|
89
|
+
total_original_size += trade.size
|
|
80
90
|
else:
|
|
81
91
|
sell_events.append((-size, trade.price, trade.match_time))
|
|
92
|
+
total_original_size -= trade.size
|
|
82
93
|
|
|
83
94
|
# --- 2. 时间排序 ---
|
|
84
95
|
all_events = sorted(buy_events + sell_events, key=lambda x: x[2])
|
|
@@ -118,20 +129,25 @@ def calculate_position_from_trades(
|
|
|
118
129
|
|
|
119
130
|
# --- 4. 计算最终持仓 ---
|
|
120
131
|
total_size = clean(sum(q[0] for q in buy_queue))
|
|
132
|
+
original_size = clean(total_original_size)
|
|
121
133
|
cost_basis = clean(sum(clean(q[0]) * q[1] for q in buy_queue))
|
|
122
134
|
|
|
123
135
|
# 若因误差产生 0.0000003 的 ghost position → 完全清掉
|
|
124
136
|
if abs(total_size) < EPS:
|
|
125
137
|
total_size = 0.0
|
|
126
138
|
cost_basis = 0.0
|
|
139
|
+
if abs(original_size) < EPS:
|
|
140
|
+
original_size = 0.0
|
|
127
141
|
|
|
128
142
|
avg_price = cost_basis / total_size if total_size != 0 else 0.0
|
|
129
143
|
|
|
130
144
|
return PositionResult(
|
|
131
145
|
size=total_size,
|
|
146
|
+
original_size=original_size,
|
|
132
147
|
avg_price=avg_price,
|
|
133
148
|
realized_pnl=realized_pnl,
|
|
134
149
|
amount=cost_basis,
|
|
150
|
+
fee_amount=total_fee_amount,
|
|
135
151
|
is_long=total_size > 0,
|
|
136
152
|
is_short=total_size < 0,
|
|
137
153
|
details=PositionDetails(
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9/poly_position_watcher.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: poly-position-watcher
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: polymarket proxy wallet redeem
|
|
5
5
|
Home-page: https://github.com/tosmart01/polymarket-position-watcher
|
|
6
6
|
Author: pinbar
|
|
@@ -32,7 +32,8 @@ Dynamic: requires-python
|
|
|
32
32
|
- WSS real-time tracking for `TRADE` and `ORDER` (positions + orders)
|
|
33
33
|
- HTTP polling fallback for reliability
|
|
34
34
|
- Optional fee calculation (toggle + custom formula)
|
|
35
|
-
-
|
|
35
|
+
- Position fields for fill checks:
|
|
36
|
+
`size` (post-fee net size), `original_size` (pre-fee net size), `sellable_size` (on-chain confirmed size), `fee_amount` (accumulated fee amount)
|
|
36
37
|
- Failed trades are detected and returned on positions (`has_failed`, `failed_trades`)
|
|
37
38
|
|
|
38
39
|
**Note: WSS disconnects are auto-detected and reconnected.**
|
|
@@ -71,6 +72,10 @@ with PositionWatcherService(
|
|
|
71
72
|
order: OrderMessage = service.get_order("<order_id>")
|
|
72
73
|
print(position)
|
|
73
74
|
print(order)
|
|
75
|
+
if position:
|
|
76
|
+
print("size(post-fee):", position.size)
|
|
77
|
+
print("size(pre-fee):", position.original_size)
|
|
78
|
+
print("fee_amount:", position.fee_amount)
|
|
74
79
|
service.show_positions(limit=10)
|
|
75
80
|
service.show_orders(limit=10)
|
|
76
81
|
|
|
@@ -113,7 +118,9 @@ OrderMessage(
|
|
|
113
118
|
UserPosition(
|
|
114
119
|
price: 0.0,
|
|
115
120
|
size: 0.0,
|
|
121
|
+
original_size: 0.0,
|
|
116
122
|
volume: 0.0,
|
|
123
|
+
fee_amount: 0.0,
|
|
117
124
|
sellable_size: 0.0,
|
|
118
125
|
token_id: '',
|
|
119
126
|
last_update: 0.0,
|
|
@@ -145,6 +152,8 @@ Some Polymarket markets enable taker fee / maker rebate. This library **fully su
|
|
|
145
152
|
- Enable with `enable_fee_calc=True` to apply fees using `feeRateBps` from trades/orders
|
|
146
153
|
- Customize with `fee_calc_fn` if you need a different formula
|
|
147
154
|
- Disable (default) if you prefer pre-fee positions
|
|
155
|
+
- Returned position fields:
|
|
156
|
+
`size` = post-fee net size, `original_size` = pre-fee net size, `fee_amount` = accumulated fee amount
|
|
148
157
|
|
|
149
158
|
Default fee formula (when `fee_calc_fn` is not provided):
|
|
150
159
|
`fee = 0.25 * (p * (1 - p)) ** 2 * (fee_rate_bps / 1000)`, and `new_size = (1 - fee) * size`.
|
|
@@ -24,7 +24,7 @@ for cache_dir in HERE.rglob("__pycache__"):
|
|
|
24
24
|
|
|
25
25
|
setup(
|
|
26
26
|
name=PROJECT.get("name", "poly-position-watcher"),
|
|
27
|
-
version=PROJECT.get("version", "0.2.
|
|
27
|
+
version=PROJECT.get("version", "0.2.9"),
|
|
28
28
|
description=PROJECT.get("description", ""),
|
|
29
29
|
long_description=README_PATH.read_text(encoding="utf-8") if README_PATH.exists() else "",
|
|
30
30
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/__init__.py
RENAMED
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/api_worker.py
RENAMED
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/__init__.py
RENAMED
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/enums.py
RENAMED
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/logger.py
RENAMED
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/__init__.py
RENAMED
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/base.py
RENAMED
|
File without changes
|
|
File without changes
|
{poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/wss_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|