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.
Files changed (25) hide show
  1. {poly_position_watcher-0.2.8/poly_position_watcher.egg-info → poly_position_watcher-0.2.9}/PKG-INFO +11 -2
  2. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/README.md +10 -1
  3. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/_version.py +1 -1
  4. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/position_service.py +2 -0
  5. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/position_model.py +4 -0
  6. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/trade_calculator.py +21 -5
  7. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9/poly_position_watcher.egg-info}/PKG-INFO +11 -2
  8. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/pyproject.toml +1 -1
  9. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/setup.py +1 -1
  10. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/LICENSE +0 -0
  11. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/MANIFEST.in +0 -0
  12. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/__init__.py +0 -0
  13. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/api_worker.py +0 -0
  14. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/__init__.py +0 -0
  15. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/enums.py +0 -0
  16. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/common/logger.py +0 -0
  17. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/__init__.py +0 -0
  18. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/base.py +0 -0
  19. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/schema/common_model.py +0 -0
  20. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher/wss_worker.py +0 -0
  21. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/SOURCES.txt +0 -0
  22. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/dependency_links.txt +0 -0
  23. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/requires.txt +0 -0
  24. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/poly_position_watcher.egg-info/top_level.txt +0 -0
  25. {poly_position_watcher-0.2.8 → poly_position_watcher-0.2.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: poly-position-watcher
3
- Version: 0.2.8
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
- - Two sizes exposed: `size` for CLOB matched trades, `sellable_size` for on-chain confirmed trades
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
- - Two sizes exposed: `size` for CLOB matched trades, `sellable_size` for on-chain confirmed trades
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`.
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "0.2.8"
3
+ __version__ = "0.2.9"
@@ -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
- return calc(size, price, fee_rate_bps)
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(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: poly-position-watcher
3
- Version: 0.2.8
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
- - Two sizes exposed: `size` for CLOB matched trades, `sellable_size` for on-chain confirmed trades
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`.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "poly-position-watcher"
3
- version = "0.2.8"
3
+ version = "0.2.9"
4
4
  description = "polymarket proxy wallet redeem"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -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.8"),
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",