avantis-trader-sdk 0.8.2__py3-none-any.whl → 0.8.4__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.
Files changed (40) hide show
  1. avantis_trader_sdk/__init__.py +5 -5
  2. avantis_trader_sdk/abis/AggregatorV3Interface.json +606 -606
  3. avantis_trader_sdk/abis/IPyth.sol/IPyth.dbg.json +4 -4
  4. avantis_trader_sdk/abis/Referral.sol/ReferralStorage.json +7132 -7132
  5. avantis_trader_sdk/abis/Sanctions.json +190 -190
  6. avantis_trader_sdk/abis/Trading.sol/Trading.json +1 -1
  7. avantis_trader_sdk/abis/USDC.sol/USDC.dbg.json +4 -4
  8. avantis_trader_sdk/abis/interfaces/ICallbacks.sol/ICallbacks.json +2637 -2637
  9. avantis_trader_sdk/abis/interfaces/IExecute.sol/IExecute.json +1628 -1628
  10. avantis_trader_sdk/abis/interfaces/IPairInfos.sol/IPairInfos.json +2781 -2781
  11. avantis_trader_sdk/abis/interfaces/IPairStorage.sol/IPairStorage.json +3729 -3729
  12. avantis_trader_sdk/abis/interfaces/IPriceAggregator.sol/IPriceAggregator.json +2330 -2330
  13. avantis_trader_sdk/abis/interfaces/IReferral.sol/IReferral.json +1890 -1890
  14. avantis_trader_sdk/abis/interfaces/ITradingStorage.sol/ITradingStorage.json +7022 -7022
  15. avantis_trader_sdk/abis/interfaces/ITranche.sol/ITranche.json +1283 -1283
  16. avantis_trader_sdk/abis/interfaces/IVaultManager.sol/IVaultManager.json +2424 -2424
  17. avantis_trader_sdk/abis/interfaces/IVeTranche.sol/IVeTranche.json +855 -855
  18. avantis_trader_sdk/abis/library/PositionMath.sol/PositionMath.dbg.json +4 -4
  19. avantis_trader_sdk/abis/library/PositionMath.sol/PositionMath.json +10 -10
  20. avantis_trader_sdk/abis/testnet/USDC.sol/USDC.dbg.json +4 -4
  21. avantis_trader_sdk/abis/testnet/USDC.sol/USDC.json +320 -320
  22. avantis_trader_sdk/client.py +369 -367
  23. avantis_trader_sdk/config.py +14 -14
  24. avantis_trader_sdk/feed/feed_client.py +263 -261
  25. avantis_trader_sdk/rpc/asset_parameters.py +499 -499
  26. avantis_trader_sdk/rpc/blended.py +71 -71
  27. avantis_trader_sdk/rpc/category_parameters.py +216 -216
  28. avantis_trader_sdk/rpc/fee_parameters.py +237 -237
  29. avantis_trader_sdk/rpc/pairs_cache.py +130 -130
  30. avantis_trader_sdk/rpc/rpc_helpers.py +8 -8
  31. avantis_trader_sdk/rpc/snapshot.py +142 -142
  32. avantis_trader_sdk/rpc/trade.py +701 -710
  33. avantis_trader_sdk/rpc/trading_parameters.py +139 -139
  34. avantis_trader_sdk/types.py +462 -462
  35. avantis_trader_sdk/utils.py +78 -78
  36. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.4.dist-info}/METADATA +124 -113
  37. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.4.dist-info}/RECORD +39 -40
  38. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.4.dist-info}/WHEEL +1 -1
  39. avantis_trader_sdk/feed/feedIds.json +0 -214
  40. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.4.dist-info}/top_level.txt +0 -0
@@ -1,71 +1,71 @@
1
- import asyncio
2
- from ..types import Utilization, Skew
3
-
4
-
5
- class BlendedRPC:
6
- """
7
- This class provides methods to retrieve and calculate various blended parameters
8
- """
9
-
10
- def __init__(self, client):
11
- """
12
- Constructor for the BlendedRPC class.
13
-
14
- Args:
15
- client: The TraderClient object.
16
- """
17
- self.client = client
18
-
19
- async def get_blended_utilization_ratio(self):
20
- """
21
- Retrieves the blended utilization ratio for all trading pairs.
22
-
23
- Returns:
24
- A Utilization instance containing the blended utilization ratio for each trading pair.
25
- """
26
- pairs_info = await self.client.pairs_cache.get_pairs_info()
27
- asset_task = self.client.asset_parameters.get_utilization()
28
- category_task = self.client.category_parameters.get_utilization()
29
-
30
- asset_utilization, category_utilization = await asyncio.gather(
31
- asset_task, category_task
32
- )
33
-
34
- utilization = {}
35
-
36
- for _, pair in pairs_info.items():
37
- if str(pair.group_index) in category_utilization.utilization:
38
- utilization[pair.from_ + "/" + pair.to] = (
39
- asset_utilization.utilization[pair.from_ + "/" + pair.to] * 25
40
- + category_utilization.utilization[str(pair.group_index)] * 75
41
- ) / 100
42
- else:
43
- utilization[pair.from_ + "/" + pair.to] = 0
44
-
45
- return Utilization(utilization=utilization)
46
-
47
- async def get_blended_skew(self):
48
- """
49
- Retrieves the blended skew for all trading pairs.
50
-
51
- Returns:
52
- A Skew instance containing the blended skew for each trading pair.
53
- """
54
- pairs_info = await self.client.pairs_cache.get_pairs_info()
55
- asset_task = self.client.asset_parameters.get_asset_skew()
56
- category_task = self.client.category_parameters.get_category_skew()
57
-
58
- asset_skew, category_skew = await asyncio.gather(asset_task, category_task)
59
-
60
- skew = {}
61
-
62
- for _, pair in pairs_info.items():
63
- if str(pair.group_index) in category_skew.skew:
64
- skew[pair.from_ + "/" + pair.to] = (
65
- asset_skew.skew[pair.from_ + "/" + pair.to] * 25
66
- + category_skew.skew[str(pair.group_index)] * 75
67
- ) / 100
68
- else:
69
- skew[pair.from_ + "/" + pair.to] = 0
70
-
71
- return Skew(skew=skew)
1
+ import asyncio
2
+ from ..types import Utilization, Skew
3
+
4
+
5
+ class BlendedRPC:
6
+ """
7
+ This class provides methods to retrieve and calculate various blended parameters
8
+ """
9
+
10
+ def __init__(self, client):
11
+ """
12
+ Constructor for the BlendedRPC class.
13
+
14
+ Args:
15
+ client: The TraderClient object.
16
+ """
17
+ self.client = client
18
+
19
+ async def get_blended_utilization_ratio(self):
20
+ """
21
+ Retrieves the blended utilization ratio for all trading pairs.
22
+
23
+ Returns:
24
+ A Utilization instance containing the blended utilization ratio for each trading pair.
25
+ """
26
+ pairs_info = await self.client.pairs_cache.get_pairs_info()
27
+ asset_task = self.client.asset_parameters.get_utilization()
28
+ category_task = self.client.category_parameters.get_utilization()
29
+
30
+ asset_utilization, category_utilization = await asyncio.gather(
31
+ asset_task, category_task
32
+ )
33
+
34
+ utilization = {}
35
+
36
+ for _, pair in pairs_info.items():
37
+ if str(pair.group_index) in category_utilization.utilization:
38
+ utilization[pair.from_ + "/" + pair.to] = (
39
+ asset_utilization.utilization[pair.from_ + "/" + pair.to] * 25
40
+ + category_utilization.utilization[str(pair.group_index)] * 75
41
+ ) / 100
42
+ else:
43
+ utilization[pair.from_ + "/" + pair.to] = 0
44
+
45
+ return Utilization(utilization=utilization)
46
+
47
+ async def get_blended_skew(self):
48
+ """
49
+ Retrieves the blended skew for all trading pairs.
50
+
51
+ Returns:
52
+ A Skew instance containing the blended skew for each trading pair.
53
+ """
54
+ pairs_info = await self.client.pairs_cache.get_pairs_info()
55
+ asset_task = self.client.asset_parameters.get_asset_skew()
56
+ category_task = self.client.category_parameters.get_category_skew()
57
+
58
+ asset_skew, category_skew = await asyncio.gather(asset_task, category_task)
59
+
60
+ skew = {}
61
+
62
+ for _, pair in pairs_info.items():
63
+ if str(pair.group_index) in category_skew.skew:
64
+ skew[pair.from_ + "/" + pair.to] = (
65
+ asset_skew.skew[pair.from_ + "/" + pair.to] * 25
66
+ + category_skew.skew[str(pair.group_index)] * 75
67
+ ) / 100
68
+ else:
69
+ skew[pair.from_ + "/" + pair.to] = 0
70
+
71
+ return Skew(skew=skew)
@@ -1,216 +1,216 @@
1
- import asyncio
2
- from ..types import OpenInterest, OpenInterestLimits, Utilization, Skew
3
-
4
-
5
- class CategoryParametersRPC:
6
- """
7
- This class provides methods to retrieve and calculate various category parameters
8
- related to open interest, open interest limits, and category utilization.
9
- """
10
-
11
- def __init__(self, client):
12
- """
13
- Constructor for the CategoryParametersRPC class.
14
-
15
- Args:
16
- client: The TraderClient object.
17
- """
18
- self.client = client
19
-
20
- async def get_oi_limits(self):
21
- """
22
- Retrieves the open interest limits for all categories.
23
-
24
- Returns:
25
- An OpenInterestLimits instance containing the open interest limits. The index of the list
26
- corresponds to the category index.
27
- """
28
- PairStorage = self.client.contracts.get("PairStorage")
29
- Multicall = self.client.contracts.get("Multicall")
30
- pairs_info = await self.client.pairs_cache.get_pairs_info()
31
- group_indexes = await self.client.pairs_cache.get_group_indexes()
32
-
33
- pair_indexes = []
34
- for group_index in group_indexes:
35
- for _, pair in pairs_info.items():
36
- if pair.group_index == group_index:
37
- pair_indexes.append(pair.fee_index)
38
- break
39
-
40
- calls = []
41
- for pair_index in pair_indexes:
42
- call_data = PairStorage.encodeABI(fn_name="groupMaxOI", args=[pair_index])
43
- calls.append((PairStorage.address, call_data))
44
-
45
- response = await Multicall.functions.aggregate(calls).call()
46
- decoded_response = [
47
- int.from_bytes(value, byteorder="big") / 10**6 for value in response[1]
48
- ]
49
- decoded_response = {
50
- str(group_index): value
51
- for group_index, value in zip(group_indexes, decoded_response)
52
- }
53
- return OpenInterestLimits(limits=decoded_response)
54
-
55
- async def get_oi(self):
56
- """
57
- Retrieves the current open interest for all categories.
58
-
59
- Returns:
60
- An OpenInterest instance containing the long and short open interest
61
- """
62
- PairStorage = self.client.contracts.get("PairStorage")
63
- Multicall = self.client.contracts.get("Multicall")
64
- group_indexes = await self.client.pairs_cache.get_group_indexes()
65
-
66
- long_calls = []
67
- short_calls = []
68
- for group_index in group_indexes:
69
- call_data = PairStorage.encodeABI(fn_name="groupOIs", args=[group_index, 0])
70
- long_calls.append((PairStorage.address, call_data))
71
-
72
- call_data = PairStorage.encodeABI(fn_name="groupOIs", args=[group_index, 1])
73
- short_calls.append((PairStorage.address, call_data))
74
-
75
- long_task = Multicall.functions.aggregate(long_calls).call()
76
- short_task = Multicall.functions.aggregate(short_calls).call()
77
-
78
- long_response, short_response = await asyncio.gather(long_task, short_task)
79
-
80
- long_response = [
81
- int.from_bytes(value, byteorder="big") / 10**6 for value in long_response[1]
82
- ]
83
- short_response = [
84
- int.from_bytes(value, byteorder="big") / 10**6
85
- for value in short_response[1]
86
- ]
87
-
88
- long_response = {
89
- str(group_index): value
90
- for group_index, value in zip(group_indexes, long_response)
91
- }
92
- short_response = {
93
- str(group_index): value
94
- for group_index, value in zip(group_indexes, short_response)
95
- }
96
-
97
- return OpenInterest(long=long_response, short=short_response)
98
-
99
- # async def get_oi(self):
100
- # """
101
- # Retrieves the current open interest for all categories.
102
-
103
- # Returns:
104
- # An OpenInterest instance containing the long and short open interest
105
- # """
106
- # pair_info = await self.client.pairs_cache.get_pairs_info()
107
- # pair_oi = await self.client.asset_parameters.get_oi()
108
- # group_indexes = await self.client.pairs_cache.get_group_indexes()
109
-
110
- # long_response = {}
111
- # short_response = {}
112
-
113
- # for group_index in group_indexes:
114
- # long_response[group_index] = 0
115
- # short_response[group_index] = 0
116
-
117
- # for pair_key, oi in pair_oi.long.items():
118
- # if pair_key in self.client.pairs_cache._pair_mapping:
119
- # pair_index = self.client.pairs_cache._pair_mapping[pair_key]
120
- # pair = pair_info[pair_index]
121
- # group_index = pair.group_index
122
- # long_response[group_index] += oi
123
- # # Assuming pair_oi.short has the same keys as pair_oi.long
124
- # short_response[group_index] += pair_oi.short[pair_key]
125
- # else:
126
- # print(f"Warning: {pair_key} not found in pair_info")
127
-
128
- # return OpenInterest(long=long_response, short=short_response)
129
-
130
- # async def get_utilization(self):
131
- # """
132
- # Calculates the category utilization for all categories.
133
-
134
- # Returns:
135
- # A Utilization instance containing the category utilization
136
- # percentage % for each category.
137
- # """
138
- # PairStorage = self.client.contracts.get("PairStorage")
139
- # Multicall = self.client.contracts.get("Multicall")
140
- # pairs_info = await self.client.pairs_cache.get_pairs_info()
141
- # group_indexes = await self.client.pairs_cache.get_group_indexes()
142
-
143
- # pair_indexes = []
144
- # for group_index in group_indexes:
145
- # for _, pair in pairs_info.items():
146
- # if pair.group_index == group_index:
147
- # pair_indexes.append(pair.fee_index)
148
- # break
149
-
150
- # calls = []
151
- # for pair_index in pair_indexes:
152
- # call_data = PairStorage.encodeABI(fn_name="groupOI", args=[pair_index])
153
- # calls.append((PairStorage.address, call_data))
154
-
155
- # oi_limits_task = self.get_oi_limits()
156
- # aggregate_task = Multicall.functions.aggregate(calls).call()
157
-
158
- # oi_limits, aggregate_response = await asyncio.gather(
159
- # oi_limits_task, aggregate_task
160
- # )
161
-
162
- # utilization = {}
163
-
164
- # for pair_index in range(len(aggregate_response[1])):
165
- # current_oi = (
166
- # int.from_bytes(aggregate_response[1][pair_index], byteorder="big")
167
- # / 10**6
168
- # )
169
- # limit = oi_limits.limits[str(pair_index)]
170
- # print(current_oi, limit)
171
- # utilization[pair_index] = current_oi * 100 / limit if limit else 0
172
-
173
- # return Utilization(utilization=utilization)
174
-
175
- async def get_utilization(self):
176
- """
177
- Calculates the category utilization for all categories.
178
-
179
- Returns:
180
- A Utilization instance containing the category utilization
181
- absolute value for each category.
182
- """
183
- oi_limits_task = self.get_oi_limits()
184
- oi_task = self.get_oi()
185
-
186
- oi_limits, oi = await asyncio.gather(oi_limits_task, oi_task)
187
-
188
- utilization = {}
189
-
190
- for group_index in range(len(oi.long)):
191
- current_oi = oi.long[str(group_index)] + oi.short[str(group_index)]
192
- limit = oi_limits.limits[str(group_index)]
193
- utilization[str(group_index)] = current_oi / limit if limit else 0
194
-
195
- return Utilization(utilization=utilization)
196
-
197
- async def get_category_skew(self):
198
- """
199
- Calculates the category skew for all categories.
200
-
201
- Returns:
202
- An Skew instance containing the category skew
203
- absolute value for each category.
204
- """
205
- oi = await self.get_oi()
206
-
207
- skew = {}
208
- for group_index, long_ratio in oi.long.items():
209
- short_ratio = oi.short[group_index]
210
- skew[group_index] = (
211
- long_ratio / (long_ratio + short_ratio)
212
- if long_ratio + short_ratio
213
- else 0
214
- )
215
-
216
- return Skew(skew=skew)
1
+ import asyncio
2
+ from ..types import OpenInterest, OpenInterestLimits, Utilization, Skew
3
+
4
+
5
+ class CategoryParametersRPC:
6
+ """
7
+ This class provides methods to retrieve and calculate various category parameters
8
+ related to open interest, open interest limits, and category utilization.
9
+ """
10
+
11
+ def __init__(self, client):
12
+ """
13
+ Constructor for the CategoryParametersRPC class.
14
+
15
+ Args:
16
+ client: The TraderClient object.
17
+ """
18
+ self.client = client
19
+
20
+ async def get_oi_limits(self):
21
+ """
22
+ Retrieves the open interest limits for all categories.
23
+
24
+ Returns:
25
+ An OpenInterestLimits instance containing the open interest limits. The index of the list
26
+ corresponds to the category index.
27
+ """
28
+ PairStorage = self.client.contracts.get("PairStorage")
29
+ Multicall = self.client.contracts.get("Multicall")
30
+ pairs_info = await self.client.pairs_cache.get_pairs_info()
31
+ group_indexes = await self.client.pairs_cache.get_group_indexes()
32
+
33
+ pair_indexes = []
34
+ for group_index in group_indexes:
35
+ for _, pair in pairs_info.items():
36
+ if pair.group_index == group_index:
37
+ pair_indexes.append(pair.fee_index)
38
+ break
39
+
40
+ calls = []
41
+ for pair_index in pair_indexes:
42
+ call_data = PairStorage.encodeABI(fn_name="groupMaxOI", args=[pair_index])
43
+ calls.append((PairStorage.address, call_data))
44
+
45
+ response = await Multicall.functions.aggregate(calls).call()
46
+ decoded_response = [
47
+ int.from_bytes(value, byteorder="big") / 10**6 for value in response[1]
48
+ ]
49
+ decoded_response = {
50
+ str(group_index): value
51
+ for group_index, value in zip(group_indexes, decoded_response)
52
+ }
53
+ return OpenInterestLimits(limits=decoded_response)
54
+
55
+ async def get_oi(self):
56
+ """
57
+ Retrieves the current open interest for all categories.
58
+
59
+ Returns:
60
+ An OpenInterest instance containing the long and short open interest
61
+ """
62
+ PairStorage = self.client.contracts.get("PairStorage")
63
+ Multicall = self.client.contracts.get("Multicall")
64
+ group_indexes = await self.client.pairs_cache.get_group_indexes()
65
+
66
+ long_calls = []
67
+ short_calls = []
68
+ for group_index in group_indexes:
69
+ call_data = PairStorage.encodeABI(fn_name="groupOIs", args=[group_index, 0])
70
+ long_calls.append((PairStorage.address, call_data))
71
+
72
+ call_data = PairStorage.encodeABI(fn_name="groupOIs", args=[group_index, 1])
73
+ short_calls.append((PairStorage.address, call_data))
74
+
75
+ long_task = Multicall.functions.aggregate(long_calls).call()
76
+ short_task = Multicall.functions.aggregate(short_calls).call()
77
+
78
+ long_response, short_response = await asyncio.gather(long_task, short_task)
79
+
80
+ long_response = [
81
+ int.from_bytes(value, byteorder="big") / 10**6 for value in long_response[1]
82
+ ]
83
+ short_response = [
84
+ int.from_bytes(value, byteorder="big") / 10**6
85
+ for value in short_response[1]
86
+ ]
87
+
88
+ long_response = {
89
+ str(group_index): value
90
+ for group_index, value in zip(group_indexes, long_response)
91
+ }
92
+ short_response = {
93
+ str(group_index): value
94
+ for group_index, value in zip(group_indexes, short_response)
95
+ }
96
+
97
+ return OpenInterest(long=long_response, short=short_response)
98
+
99
+ # async def get_oi(self):
100
+ # """
101
+ # Retrieves the current open interest for all categories.
102
+
103
+ # Returns:
104
+ # An OpenInterest instance containing the long and short open interest
105
+ # """
106
+ # pair_info = await self.client.pairs_cache.get_pairs_info()
107
+ # pair_oi = await self.client.asset_parameters.get_oi()
108
+ # group_indexes = await self.client.pairs_cache.get_group_indexes()
109
+
110
+ # long_response = {}
111
+ # short_response = {}
112
+
113
+ # for group_index in group_indexes:
114
+ # long_response[group_index] = 0
115
+ # short_response[group_index] = 0
116
+
117
+ # for pair_key, oi in pair_oi.long.items():
118
+ # if pair_key in self.client.pairs_cache._pair_mapping:
119
+ # pair_index = self.client.pairs_cache._pair_mapping[pair_key]
120
+ # pair = pair_info[pair_index]
121
+ # group_index = pair.group_index
122
+ # long_response[group_index] += oi
123
+ # # Assuming pair_oi.short has the same keys as pair_oi.long
124
+ # short_response[group_index] += pair_oi.short[pair_key]
125
+ # else:
126
+ # print(f"Warning: {pair_key} not found in pair_info")
127
+
128
+ # return OpenInterest(long=long_response, short=short_response)
129
+
130
+ # async def get_utilization(self):
131
+ # """
132
+ # Calculates the category utilization for all categories.
133
+
134
+ # Returns:
135
+ # A Utilization instance containing the category utilization
136
+ # percentage % for each category.
137
+ # """
138
+ # PairStorage = self.client.contracts.get("PairStorage")
139
+ # Multicall = self.client.contracts.get("Multicall")
140
+ # pairs_info = await self.client.pairs_cache.get_pairs_info()
141
+ # group_indexes = await self.client.pairs_cache.get_group_indexes()
142
+
143
+ # pair_indexes = []
144
+ # for group_index in group_indexes:
145
+ # for _, pair in pairs_info.items():
146
+ # if pair.group_index == group_index:
147
+ # pair_indexes.append(pair.fee_index)
148
+ # break
149
+
150
+ # calls = []
151
+ # for pair_index in pair_indexes:
152
+ # call_data = PairStorage.encodeABI(fn_name="groupOI", args=[pair_index])
153
+ # calls.append((PairStorage.address, call_data))
154
+
155
+ # oi_limits_task = self.get_oi_limits()
156
+ # aggregate_task = Multicall.functions.aggregate(calls).call()
157
+
158
+ # oi_limits, aggregate_response = await asyncio.gather(
159
+ # oi_limits_task, aggregate_task
160
+ # )
161
+
162
+ # utilization = {}
163
+
164
+ # for pair_index in range(len(aggregate_response[1])):
165
+ # current_oi = (
166
+ # int.from_bytes(aggregate_response[1][pair_index], byteorder="big")
167
+ # / 10**6
168
+ # )
169
+ # limit = oi_limits.limits[str(pair_index)]
170
+ # print(current_oi, limit)
171
+ # utilization[pair_index] = current_oi * 100 / limit if limit else 0
172
+
173
+ # return Utilization(utilization=utilization)
174
+
175
+ async def get_utilization(self):
176
+ """
177
+ Calculates the category utilization for all categories.
178
+
179
+ Returns:
180
+ A Utilization instance containing the category utilization
181
+ absolute value for each category.
182
+ """
183
+ oi_limits_task = self.get_oi_limits()
184
+ oi_task = self.get_oi()
185
+
186
+ oi_limits, oi = await asyncio.gather(oi_limits_task, oi_task)
187
+
188
+ utilization = {}
189
+
190
+ for group_index in range(len(oi.long)):
191
+ current_oi = oi.long[str(group_index)] + oi.short[str(group_index)]
192
+ limit = oi_limits.limits[str(group_index)]
193
+ utilization[str(group_index)] = current_oi / limit if limit else 0
194
+
195
+ return Utilization(utilization=utilization)
196
+
197
+ async def get_category_skew(self):
198
+ """
199
+ Calculates the category skew for all categories.
200
+
201
+ Returns:
202
+ An Skew instance containing the category skew
203
+ absolute value for each category.
204
+ """
205
+ oi = await self.get_oi()
206
+
207
+ skew = {}
208
+ for group_index, long_ratio in oi.long.items():
209
+ short_ratio = oi.short[group_index]
210
+ skew[group_index] = (
211
+ long_ratio / (long_ratio + short_ratio)
212
+ if long_ratio + short_ratio
213
+ else 0
214
+ )
215
+
216
+ return Skew(skew=skew)