avantis-trader-sdk 0.8.2__py3-none-any.whl → 0.8.3__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 (39) 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/USDC.sol/USDC.dbg.json +4 -4
  7. avantis_trader_sdk/abis/interfaces/ICallbacks.sol/ICallbacks.json +2637 -2637
  8. avantis_trader_sdk/abis/interfaces/IExecute.sol/IExecute.json +1628 -1628
  9. avantis_trader_sdk/abis/interfaces/IPairInfos.sol/IPairInfos.json +2781 -2781
  10. avantis_trader_sdk/abis/interfaces/IPairStorage.sol/IPairStorage.json +3729 -3729
  11. avantis_trader_sdk/abis/interfaces/IPriceAggregator.sol/IPriceAggregator.json +2330 -2330
  12. avantis_trader_sdk/abis/interfaces/IReferral.sol/IReferral.json +1890 -1890
  13. avantis_trader_sdk/abis/interfaces/ITradingStorage.sol/ITradingStorage.json +7022 -7022
  14. avantis_trader_sdk/abis/interfaces/ITranche.sol/ITranche.json +1283 -1283
  15. avantis_trader_sdk/abis/interfaces/IVaultManager.sol/IVaultManager.json +2424 -2424
  16. avantis_trader_sdk/abis/interfaces/IVeTranche.sol/IVeTranche.json +855 -855
  17. avantis_trader_sdk/abis/library/PositionMath.sol/PositionMath.dbg.json +4 -4
  18. avantis_trader_sdk/abis/library/PositionMath.sol/PositionMath.json +10 -10
  19. avantis_trader_sdk/abis/testnet/USDC.sol/USDC.dbg.json +4 -4
  20. avantis_trader_sdk/abis/testnet/USDC.sol/USDC.json +320 -320
  21. avantis_trader_sdk/client.py +369 -367
  22. avantis_trader_sdk/config.py +14 -14
  23. avantis_trader_sdk/feed/feed_client.py +263 -261
  24. avantis_trader_sdk/rpc/asset_parameters.py +499 -499
  25. avantis_trader_sdk/rpc/blended.py +71 -71
  26. avantis_trader_sdk/rpc/category_parameters.py +216 -216
  27. avantis_trader_sdk/rpc/fee_parameters.py +237 -237
  28. avantis_trader_sdk/rpc/pairs_cache.py +130 -130
  29. avantis_trader_sdk/rpc/rpc_helpers.py +8 -8
  30. avantis_trader_sdk/rpc/snapshot.py +142 -142
  31. avantis_trader_sdk/rpc/trade.py +701 -710
  32. avantis_trader_sdk/rpc/trading_parameters.py +139 -139
  33. avantis_trader_sdk/types.py +462 -462
  34. avantis_trader_sdk/utils.py +78 -78
  35. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.3.dist-info}/METADATA +124 -113
  36. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.3.dist-info}/RECORD +38 -39
  37. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.3.dist-info}/WHEEL +1 -1
  38. avantis_trader_sdk/feed/feedIds.json +0 -214
  39. {avantis_trader_sdk-0.8.2.dist-info → avantis_trader_sdk-0.8.3.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)