ostium-python-sdk 2.0.5__tar.gz → 2.0.6__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.
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/PKG-INFO +7 -1
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/README.md +6 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/formulae.py +61 -27
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/ostium.py +3 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/sdk.py +15 -4
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/subgraph.py +10 -4
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/PKG-INFO +7 -1
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/SOURCES.txt +4 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/setup.py +1 -1
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_funding.py +3 -3
- ostium_python_sdk-2.0.6/tests/test_get_opening_fee.py +66 -0
- ostium_python_sdk-2.0.6/tests/test_get_trade_value.py +82 -0
- ostium_python_sdk-2.0.6/tests/test_max_leverage.py +55 -0
- ostium_python_sdk-2.0.6/tests/test_overnight_max_leverage.py +46 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/MANIFEST.in +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/__init__.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/__init__.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/faucet_testnet_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/pairs_info_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/pairs_storage_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/trading_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/trading_storage_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/usdc_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/vault_abi.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/balance.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/config.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/constants.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/exceptions.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/faucet.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/formulae_wrapper.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/price.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/scscript/__init__.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/scscript/funding.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/utils.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/dependency_links.txt +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/requires.txt +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/top_level.txt +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/pyproject.toml +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/requirements-dev.txt +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/requirements.txt +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/setup.cfg +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/__init__.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_current_total_profit_p.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_current_total_profit_raw.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_current_trade_profit_p.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_current_trade_profit_raw.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_get_price_impact.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_get_trade_funding_fee.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_get_trade_rollover_fee.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_remove_collateral_from_leverage.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_remove_collateral_with_collateral.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_slippage.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_top_up_with_collateral.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_top_up_with_leverage.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_trade_get_sl_price.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_trade_get_tp_price.py +0 -0
- {ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_trade_liquidation_price.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ostium-python-sdk
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.6
|
|
4
4
|
Summary: A python based SDK developed for interacting with Ostium, a leveraged trading application for trading currencies, commodities, indices, crypto and more.
|
|
5
5
|
Home-page: https://github.com/0xOstium/ostium-python-sdk
|
|
6
6
|
Author: ami@ostium.io
|
|
@@ -106,6 +106,12 @@ pytest -v tests/test_current_trade_profit_raw.py
|
|
|
106
106
|
pytest -v tests/test_current_total_profit_raw.py
|
|
107
107
|
pytest -v tests/test_get_trade_funding_fee.py
|
|
108
108
|
pytest -v tests/test_get_trade_rollover_fee.py
|
|
109
|
+
pytest -v tests/test_get_trade_value.py
|
|
110
|
+
pytest -v tests/test_get_opening_fee.py
|
|
111
|
+
|
|
112
|
+
pytest -v tests/test_max_leverage.py
|
|
113
|
+
pytest -v tests/test_overnight_max_leverage.py
|
|
114
|
+
pytest -v tests/test_slippage.py
|
|
109
115
|
|
|
110
116
|
|
|
111
117
|
|
|
@@ -67,6 +67,12 @@ pytest -v tests/test_current_trade_profit_raw.py
|
|
|
67
67
|
pytest -v tests/test_current_total_profit_raw.py
|
|
68
68
|
pytest -v tests/test_get_trade_funding_fee.py
|
|
69
69
|
pytest -v tests/test_get_trade_rollover_fee.py
|
|
70
|
+
pytest -v tests/test_get_trade_value.py
|
|
71
|
+
pytest -v tests/test_get_opening_fee.py
|
|
72
|
+
|
|
73
|
+
pytest -v tests/test_max_leverage.py
|
|
74
|
+
pytest -v tests/test_overnight_max_leverage.py
|
|
75
|
+
pytest -v tests/test_slippage.py
|
|
70
76
|
|
|
71
77
|
|
|
72
78
|
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
from decimal import Decimal, getcontext, ROUND_DOWN
|
|
2
|
-
from .constants import MAX_PROFIT_P, MIN_LOSS_P,
|
|
2
|
+
from .constants import MAX_PROFIT_P, MIN_LOSS_P, PRECISION_2, PRECISION_6, PRECISION_18
|
|
3
3
|
from typing import Dict
|
|
4
4
|
from .scscript.funding import getPendingAccFundingFees, getTargetFundingRate
|
|
5
5
|
|
|
6
6
|
quantization_6 = Decimal('0.000001')
|
|
7
7
|
quantization_18 = Decimal('0.000000000000000001')
|
|
8
8
|
|
|
9
|
-
# v2 (formulae v1.3.3)
|
|
10
|
-
|
|
11
9
|
|
|
12
10
|
def GetTakeProfitPrice(open_price: Decimal, profit_p: Decimal, leverage: Decimal, is_long: bool) -> Decimal:
|
|
13
11
|
open_price = Decimal(open_price)
|
|
@@ -23,8 +21,6 @@ def GetTakeProfitPrice(open_price: Decimal, profit_p: Decimal, leverage: Decimal
|
|
|
23
21
|
|
|
24
22
|
return Decimal(tp_price if tp_price > 0 else '0')
|
|
25
23
|
|
|
26
|
-
# v2 (formulae v1.3.3)
|
|
27
|
-
|
|
28
24
|
|
|
29
25
|
def GetStopLossPrice(open_price: Decimal, loss_p: Decimal, leverage: Decimal, is_long: bool) -> Decimal:
|
|
30
26
|
open_price = Decimal(open_price)
|
|
@@ -37,8 +33,6 @@ def GetStopLossPrice(open_price: Decimal, loss_p: Decimal, leverage: Decimal, is
|
|
|
37
33
|
sl_price = open_price - price_diff if is_long else open_price + price_diff
|
|
38
34
|
return sl_price if sl_price > 0 else Decimal('0')
|
|
39
35
|
|
|
40
|
-
# v2 (formulae v1.3.3)
|
|
41
|
-
|
|
42
36
|
|
|
43
37
|
def CurrentTradeProfitP(
|
|
44
38
|
open_price: Decimal,
|
|
@@ -62,8 +56,6 @@ def CurrentTradeProfitP(
|
|
|
62
56
|
|
|
63
57
|
return profit_p
|
|
64
58
|
|
|
65
|
-
# v2 (formulae v1.3.3)
|
|
66
|
-
|
|
67
59
|
|
|
68
60
|
def TopUpWithCollateral(
|
|
69
61
|
leverage: Decimal,
|
|
@@ -73,8 +65,6 @@ def TopUpWithCollateral(
|
|
|
73
65
|
new_leverage = (collateral * leverage) / (collateral + added_collateral)
|
|
74
66
|
return new_leverage
|
|
75
67
|
|
|
76
|
-
# v2 (formulae v1.3.3)
|
|
77
|
-
|
|
78
68
|
|
|
79
69
|
def TopUpWithLeverage(
|
|
80
70
|
leverage: Decimal,
|
|
@@ -84,8 +74,6 @@ def TopUpWithLeverage(
|
|
|
84
74
|
added_c = (collateral * leverage) / desired_leverage - collateral
|
|
85
75
|
return added_c
|
|
86
76
|
|
|
87
|
-
# v2 (formulae v1.3.3)
|
|
88
|
-
|
|
89
77
|
|
|
90
78
|
def RemoveCollateralWithCollateral(
|
|
91
79
|
leverage: Decimal,
|
|
@@ -95,8 +83,6 @@ def RemoveCollateralWithCollateral(
|
|
|
95
83
|
new_leverage = (collateral * leverage) / (collateral - removed_collateral)
|
|
96
84
|
return new_leverage
|
|
97
85
|
|
|
98
|
-
# v2 (formulae v1.3.3)
|
|
99
|
-
|
|
100
86
|
|
|
101
87
|
def RemoveCollateralFromLeverage(
|
|
102
88
|
leverage: Decimal,
|
|
@@ -106,9 +92,8 @@ def RemoveCollateralFromLeverage(
|
|
|
106
92
|
added_c = collateral - (collateral * leverage / desired_leverage)
|
|
107
93
|
return added_c
|
|
108
94
|
|
|
109
|
-
# tbd - used by SDK
|
|
110
|
-
# v2 (formulae v1.3.3)
|
|
111
95
|
|
|
96
|
+
# Start of copied v1.2.3
|
|
112
97
|
|
|
113
98
|
def getTradeLiquidationPrice(
|
|
114
99
|
liqMarginThresholdP: Decimal,
|
|
@@ -133,21 +118,42 @@ def getTradeLiquidationPrice(
|
|
|
133
118
|
return max(Decimal('0'), liqPrice)
|
|
134
119
|
|
|
135
120
|
|
|
121
|
+
|
|
122
|
+
|
|
136
123
|
def getTradeValue(
|
|
124
|
+
liqMarginThresholdP: Decimal, # 25 means 25%
|
|
125
|
+
collateral: Decimal,
|
|
126
|
+
percentProfit: Decimal,
|
|
127
|
+
rolloverFee: Decimal,
|
|
128
|
+
fundingFee: Decimal,
|
|
129
|
+
leverage: Decimal,
|
|
130
|
+
maxLeverage: Decimal,
|
|
131
|
+
) -> (Decimal, Decimal):
|
|
132
|
+
liqMarginValue = getTradeLiquidationMargin(
|
|
133
|
+
liqMarginThresholdP, collateral, leverage, maxLeverage)
|
|
134
|
+
value = getTradeValuePure(
|
|
135
|
+
collateral, percentProfit, rolloverFee, fundingFee, liqMarginValue)
|
|
136
|
+
|
|
137
|
+
return value, liqMarginValue
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def getTradeValuePure(
|
|
137
141
|
collateral: Decimal,
|
|
138
142
|
percentProfit: Decimal,
|
|
139
143
|
rolloverFee: Decimal,
|
|
140
|
-
fundingFee: Decimal
|
|
144
|
+
fundingFee: Decimal,
|
|
145
|
+
liqMarginValue: Decimal
|
|
141
146
|
) -> Decimal:
|
|
142
147
|
profitPart = (collateral * percentProfit / Decimal('100')
|
|
143
148
|
).quantize(quantization_6, rounding=ROUND_DOWN)
|
|
144
149
|
value = (collateral + profitPart - rolloverFee - fundingFee)
|
|
145
|
-
|
|
150
|
+
if value <= liqMarginValue:
|
|
151
|
+
return Decimal('0')
|
|
146
152
|
return value
|
|
147
153
|
|
|
148
154
|
|
|
149
155
|
def getTradeLiquidationMargin(
|
|
150
|
-
liqMarginThresholdP: Decimal,
|
|
156
|
+
liqMarginThresholdP: Decimal, # 0.25 means 25%
|
|
151
157
|
collateral: Decimal,
|
|
152
158
|
leverage: Decimal,
|
|
153
159
|
maxLeverage: Decimal
|
|
@@ -157,7 +163,39 @@ def getTradeLiquidationMargin(
|
|
|
157
163
|
return (collateral * rawAdjustedThreshold / Decimal('100')).quantize(quantization_6, rounding=ROUND_DOWN)
|
|
158
164
|
|
|
159
165
|
|
|
160
|
-
|
|
166
|
+
def getOpeningFee(
|
|
167
|
+
tradeSize: Decimal,
|
|
168
|
+
leverage: Decimal,
|
|
169
|
+
oiDelta: Decimal,
|
|
170
|
+
makerMaxLeverage: Decimal,
|
|
171
|
+
makerFeeP: Decimal,
|
|
172
|
+
takerFeeP: Decimal
|
|
173
|
+
) -> Decimal:
|
|
174
|
+
makerAmount: Decimal = Decimal(0)
|
|
175
|
+
takerAmount: Decimal = Decimal(0)
|
|
176
|
+
|
|
177
|
+
print(f"tradeSize: {tradeSize}, leverage: {leverage}, oiDelta: {oiDelta}, makerMaxLeverage: {makerMaxLeverage}, makerFeeP: {makerFeeP}, takerFeeP: {takerFeeP}")
|
|
178
|
+
# Base Fee
|
|
179
|
+
if (oiDelta * tradeSize < 0 and leverage <= makerMaxLeverage):
|
|
180
|
+
if (oiDelta * (oiDelta + tradeSize) >= 0):
|
|
181
|
+
makerAmount = abs(tradeSize)
|
|
182
|
+
else:
|
|
183
|
+
makerAmount = abs(oiDelta)
|
|
184
|
+
takerAmount = abs(oiDelta + tradeSize)
|
|
185
|
+
else:
|
|
186
|
+
takerAmount = abs(tradeSize)
|
|
187
|
+
|
|
188
|
+
baseFee: Decimal = (
|
|
189
|
+
(makerFeeP * makerAmount).quantize(quantization_6, rounding=ROUND_DOWN) +
|
|
190
|
+
(takerFeeP * takerAmount).quantize(quantization_6, rounding=ROUND_DOWN)
|
|
191
|
+
) / Decimal('100')
|
|
192
|
+
|
|
193
|
+
return baseFee.quantize(quantization_6, rounding=ROUND_DOWN)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# End of copied v1.2.3
|
|
197
|
+
|
|
198
|
+
|
|
161
199
|
def GetCurrentRolloverFee(
|
|
162
200
|
acc_rollover: str,
|
|
163
201
|
last_rollover_block: str,
|
|
@@ -177,7 +215,6 @@ def GetCurrentRolloverFee(
|
|
|
177
215
|
raise Exception(f"Unable to compute Current Rollover Fee: {error}")
|
|
178
216
|
|
|
179
217
|
|
|
180
|
-
# v2 (formulae v1.3.3)
|
|
181
218
|
def GetTradeRolloverFee(
|
|
182
219
|
trade_rollover: Decimal,
|
|
183
220
|
current_rollover: Decimal,
|
|
@@ -189,7 +226,7 @@ def GetTradeRolloverFee(
|
|
|
189
226
|
|
|
190
227
|
|
|
191
228
|
# Gets the funding fee (abs) for an open trade (up to this block, aka based on current_funding up till this block)
|
|
192
|
-
|
|
229
|
+
|
|
193
230
|
def GetTradeFundingFee(
|
|
194
231
|
trade_funding: Decimal,
|
|
195
232
|
current_funding: Decimal,
|
|
@@ -236,7 +273,7 @@ def GetPriceImpact(
|
|
|
236
273
|
# calculates the gross (without fees) profit (abs) of an open trade
|
|
237
274
|
|
|
238
275
|
# calculates the net profit (after fees) of an open trade (abs)
|
|
239
|
-
|
|
276
|
+
|
|
240
277
|
def CurrentTradeProfitRaw(
|
|
241
278
|
open_price: Decimal,
|
|
242
279
|
current_price: Decimal,
|
|
@@ -255,8 +292,6 @@ def CurrentTradeProfitRaw(
|
|
|
255
292
|
profit = (collateral * profit_p) / Decimal("100")
|
|
256
293
|
return profit
|
|
257
294
|
|
|
258
|
-
# v2 (formulae v1.3.3)
|
|
259
|
-
|
|
260
295
|
|
|
261
296
|
def CurrentTotalProfitRaw(
|
|
262
297
|
open_price: Decimal,
|
|
@@ -285,7 +320,6 @@ def CurrentTotalProfitRaw(
|
|
|
285
320
|
return total_profit
|
|
286
321
|
|
|
287
322
|
|
|
288
|
-
# v2 (formulae v1.3.3)
|
|
289
323
|
def CurrentTotalProfitP(total_profit: Decimal, collateral: Decimal) -> Decimal:
|
|
290
324
|
profit_p = (total_profit * Decimal("100")) / collateral
|
|
291
325
|
if profit_p <= MIN_LOSS_P:
|
|
@@ -59,7 +59,10 @@ class OstiumSDK:
|
|
|
59
59
|
f"but RPC is connected to chain ID {actual_chain_id}. Please check your RPC_URL."
|
|
60
60
|
)
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
if self.verbose:
|
|
63
|
+
print(
|
|
64
|
+
f"network_config: {'TESTNET' if self.network_config.is_testnet else 'MAINNET'}")
|
|
65
|
+
|
|
63
66
|
# Initialize Ostium instance
|
|
64
67
|
self.ostium = Ostium(
|
|
65
68
|
self.w3,
|
|
@@ -137,12 +140,20 @@ class OstiumSDK:
|
|
|
137
140
|
|
|
138
141
|
return get_trade_metrics(trade_details, price_data, block_number, pair_max_leverage, liq_margin_threshold_p, verbose=self.verbose)
|
|
139
142
|
|
|
140
|
-
#
|
|
143
|
+
# max leverage for overnight trades (Stocks) - 100 means 100x, None if not set
|
|
144
|
+
async def get_pair_overnight_max_leverage(self, pair_id):
|
|
145
|
+
obj = await self.subgraph.get_pair_details(pair_id)
|
|
146
|
+
|
|
147
|
+
maxLeverage = int(obj['overnightMaxLeverage'])/100 if int(
|
|
148
|
+
obj['overnightMaxLeverage']) != 0 else None
|
|
149
|
+
return maxLeverage
|
|
150
|
+
|
|
151
|
+
# either by group of pair or by pair id (e.g: maxLeverage 100 means 100x )
|
|
141
152
|
async def get_pair_max_leverage(self, pair_id):
|
|
142
153
|
obj = await self.subgraph.get_pair_details(pair_id)
|
|
143
154
|
|
|
144
|
-
maxLeverage = obj['maxLeverage'] if int(
|
|
145
|
-
obj['group']['maxLeverage']) == 0 else obj['group']['maxLeverage']
|
|
155
|
+
maxLeverage = int(obj['maxLeverage']) / 100 if int(
|
|
156
|
+
obj['group']['maxLeverage']) == 0 else int(obj['group']['maxLeverage']) / 100
|
|
146
157
|
return maxLeverage
|
|
147
158
|
|
|
148
159
|
async def get_pair_net_rate_percent_per_hours(self, pair_id, period_hours=24):
|
|
@@ -26,6 +26,7 @@ class SubgraphClient:
|
|
|
26
26
|
from
|
|
27
27
|
to
|
|
28
28
|
feed
|
|
29
|
+
overnightMaxLeverage
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
"""
|
|
@@ -43,7 +44,8 @@ class SubgraphClient:
|
|
|
43
44
|
pair(id: $pair_id) {
|
|
44
45
|
id
|
|
45
46
|
from
|
|
46
|
-
to
|
|
47
|
+
to
|
|
48
|
+
overnightMaxLeverage
|
|
47
49
|
longOI
|
|
48
50
|
shortOI
|
|
49
51
|
maxOI
|
|
@@ -99,8 +101,7 @@ class SubgraphClient:
|
|
|
99
101
|
else:
|
|
100
102
|
raise ValueError(f"No pair details found for pair ID: {pair_id}")
|
|
101
103
|
|
|
102
|
-
async def get_liq_margin_threshold_p(self):
|
|
103
|
-
self.log(f"Fetching get_liq_margin_threshold_p")
|
|
104
|
+
async def get_liq_margin_threshold_p(self):
|
|
104
105
|
query = gql(
|
|
105
106
|
"""
|
|
106
107
|
query metaDatas {
|
|
@@ -112,7 +113,12 @@ class SubgraphClient:
|
|
|
112
113
|
)
|
|
113
114
|
result = await self.client.execute_async(query)
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
liq_margin_threshold_p = result['metaDatas'][0]['liqMarginThresholdP']
|
|
117
|
+
|
|
118
|
+
if self.verbose:
|
|
119
|
+
self.log(f"Fetched get_liq_margin_threshold_p: {liq_margin_threshold_p}%")
|
|
120
|
+
|
|
121
|
+
return liq_margin_threshold_p
|
|
116
122
|
|
|
117
123
|
async def get_open_trades(self, address):
|
|
118
124
|
# self.log(f"Fetching open trades for address: {address}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ostium-python-sdk
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.6
|
|
4
4
|
Summary: A python based SDK developed for interacting with Ostium, a leveraged trading application for trading currencies, commodities, indices, crypto and more.
|
|
5
5
|
Home-page: https://github.com/0xOstium/ostium-python-sdk
|
|
6
6
|
Author: ami@ostium.io
|
|
@@ -106,6 +106,12 @@ pytest -v tests/test_current_trade_profit_raw.py
|
|
|
106
106
|
pytest -v tests/test_current_total_profit_raw.py
|
|
107
107
|
pytest -v tests/test_get_trade_funding_fee.py
|
|
108
108
|
pytest -v tests/test_get_trade_rollover_fee.py
|
|
109
|
+
pytest -v tests/test_get_trade_value.py
|
|
110
|
+
pytest -v tests/test_get_opening_fee.py
|
|
111
|
+
|
|
112
|
+
pytest -v tests/test_max_leverage.py
|
|
113
|
+
pytest -v tests/test_overnight_max_leverage.py
|
|
114
|
+
pytest -v tests/test_slippage.py
|
|
109
115
|
|
|
110
116
|
|
|
111
117
|
|
|
@@ -38,9 +38,13 @@ tests/test_current_total_profit_raw.py
|
|
|
38
38
|
tests/test_current_trade_profit_p.py
|
|
39
39
|
tests/test_current_trade_profit_raw.py
|
|
40
40
|
tests/test_funding.py
|
|
41
|
+
tests/test_get_opening_fee.py
|
|
41
42
|
tests/test_get_price_impact.py
|
|
42
43
|
tests/test_get_trade_funding_fee.py
|
|
43
44
|
tests/test_get_trade_rollover_fee.py
|
|
45
|
+
tests/test_get_trade_value.py
|
|
46
|
+
tests/test_max_leverage.py
|
|
47
|
+
tests/test_overnight_max_leverage.py
|
|
44
48
|
tests/test_remove_collateral_from_leverage.py
|
|
45
49
|
tests/test_remove_collateral_with_collateral.py
|
|
46
50
|
tests/test_slippage.py
|
|
@@ -420,10 +420,10 @@ async def test_oi_delta_negative_scaled_down_spring_factor_shorts_pay_longs():
|
|
|
420
420
|
|
|
421
421
|
# 2. Expected outputs
|
|
422
422
|
expected_latest_funding_rate = Decimal(
|
|
423
|
-
'-0.
|
|
423
|
+
'-0.004999999444615238')
|
|
424
424
|
expected_acc_funding_long = Decimal(
|
|
425
|
-
'-0.
|
|
426
|
-
expected_acc_funding_short = Decimal('0.
|
|
425
|
+
'-0.499999972230743300')
|
|
426
|
+
expected_acc_funding_short = Decimal('0.004999999722307433')
|
|
427
427
|
expected_target_fr = Decimal('-0.004876580886315063')
|
|
428
428
|
|
|
429
429
|
# 3. Call function
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
from ostium_python_sdk.formulae import getOpeningFee
|
|
4
|
+
|
|
5
|
+
# Global list of all test cases
|
|
6
|
+
test_cases = [
|
|
7
|
+
# CASE-0 - test_Validate_Full_Taker_getOpeningFee
|
|
8
|
+
{
|
|
9
|
+
'trade_size': Decimal('-10000'),
|
|
10
|
+
'leverage': Decimal('3'),
|
|
11
|
+
'oi_delta': Decimal('5000'),
|
|
12
|
+
'maker_max_leverage': Decimal('10'),
|
|
13
|
+
'maker_fee_p': Decimal('0.0001'), # 100 / PRECISION_6 => 0.0001
|
|
14
|
+
'taker_fee_p': Decimal('0.0003'), # 300 / PRECISION_6 => 0.0003
|
|
15
|
+
'expected_fee': Decimal('0.02')
|
|
16
|
+
},
|
|
17
|
+
# CASE-1 - test_Validate_Negative_OiDelta_Full_Maker_getOpeningFee
|
|
18
|
+
{
|
|
19
|
+
'trade_size': Decimal('10'), # 10000000 / PRECISION_6
|
|
20
|
+
'leverage': Decimal('3'), # 300 / PRECISION_2
|
|
21
|
+
'oi_delta': Decimal('-5000'), # -5000000000 / PRECISION_6
|
|
22
|
+
'maker_max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
23
|
+
'maker_fee_p': Decimal('0.0001'), # 100 / PRECISION_6
|
|
24
|
+
'taker_fee_p': Decimal('0.0003'), # 300 / PRECISION_6
|
|
25
|
+
'expected_fee': Decimal('0.000010')
|
|
26
|
+
},
|
|
27
|
+
# CASE-2 - test_Validate_Negative_OiDelta_Maker_And_Taker_getOpeningFee
|
|
28
|
+
{
|
|
29
|
+
'trade_size': Decimal('10'), # 10000000 / PRECISION_6
|
|
30
|
+
'leverage': Decimal('3'), # 300 / PRECISION_2
|
|
31
|
+
'oi_delta': Decimal('-5'), # -5000000 / PRECISION_6
|
|
32
|
+
'maker_max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
33
|
+
'maker_fee_p': Decimal('0.0001'), # 100 / PRECISION_6
|
|
34
|
+
'taker_fee_p': Decimal('0.0003'), # 300 / PRECISION_6
|
|
35
|
+
'expected_fee': Decimal('0.000020')
|
|
36
|
+
},
|
|
37
|
+
# CASE-3 - test_Validate_Negative_OiDelta_Lower_Fees_getOpeningFee
|
|
38
|
+
{
|
|
39
|
+
'trade_size': Decimal('10'), # 10000000 / PRECISION_6
|
|
40
|
+
'leverage': Decimal('3'), # 300 / PRECISION_2
|
|
41
|
+
'oi_delta': Decimal('-5'), # -5000000 / PRECISION_6
|
|
42
|
+
'maker_max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
43
|
+
'maker_fee_p': Decimal('0.00005'), # 50 / PRECISION_6
|
|
44
|
+
'taker_fee_p': Decimal('0.0002'), # 200 / PRECISION_6
|
|
45
|
+
'expected_fee': Decimal('0.000012')
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.mark.parametrize("case", test_cases)
|
|
51
|
+
def test_get_opening_fee(case):
|
|
52
|
+
"""Test multiple scenarios for getOpeningFee with Pytest."""
|
|
53
|
+
|
|
54
|
+
fee = getOpeningFee(
|
|
55
|
+
tradeSize=case['trade_size'],
|
|
56
|
+
leverage=case['leverage'],
|
|
57
|
+
oiDelta=case['oi_delta'],
|
|
58
|
+
makerMaxLeverage=case['maker_max_leverage'],
|
|
59
|
+
makerFeeP=case['maker_fee_p'],
|
|
60
|
+
takerFeeP=case['taker_fee_p']
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Equivalent to assertAlmostEqual(..., places=5) is approx with abs=1e-5
|
|
64
|
+
# or thereabouts. Adjust as needed for your precision.
|
|
65
|
+
assert fee == pytest.approx(case['expected_fee'], abs=1e-5), \
|
|
66
|
+
f"Failed for case: {case}"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
from ostium_python_sdk.formulae import getTradeValue
|
|
4
|
+
|
|
5
|
+
# Global list of all test cases
|
|
6
|
+
test_cases = [
|
|
7
|
+
# CASE-0
|
|
8
|
+
{
|
|
9
|
+
'liq_margin_threshold_p': Decimal('25'), # 25 (no division needed)
|
|
10
|
+
'collateral': Decimal('100'), # 100000000 / PRECISION_6
|
|
11
|
+
'percent_profit': Decimal('1'), # 1000000 / PRECISION_6
|
|
12
|
+
'rollover_fee': Decimal('0.000001'), # 1 / PRECISION_6
|
|
13
|
+
'funding_fee': Decimal('0'), # 0 / PRECISION_6
|
|
14
|
+
'leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
15
|
+
'max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
16
|
+
# 100999999 / PRECISION_6
|
|
17
|
+
'expected_trade_value': Decimal('100.999999'),
|
|
18
|
+
'expected_liq_margin_value': Decimal('25'), # 25000000 / PRECISION_6
|
|
19
|
+
},
|
|
20
|
+
# CASE-1
|
|
21
|
+
{
|
|
22
|
+
'liq_margin_threshold_p': Decimal('25'), # 25 (no division needed)
|
|
23
|
+
'collateral': Decimal('100'), # 100000000 / PRECISION_6
|
|
24
|
+
'percent_profit': Decimal('87.769211'), # 87769211 / PRECISION_6
|
|
25
|
+
'rollover_fee': Decimal('1.395969'), # 1395969 / PRECISION_6
|
|
26
|
+
'funding_fee': Decimal('2.145623'), # 2145623 / PRECISION_6
|
|
27
|
+
'leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
28
|
+
'max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
29
|
+
# 184227619 / PRECISION_6
|
|
30
|
+
'expected_trade_value': Decimal('184.227619'),
|
|
31
|
+
'expected_liq_margin_value': Decimal('25'), # 25000000 / PRECISION_6
|
|
32
|
+
},
|
|
33
|
+
# CASE-2
|
|
34
|
+
{
|
|
35
|
+
'liq_margin_threshold_p': Decimal('25'), # 25 (no division needed)
|
|
36
|
+
'collateral': Decimal('200'), # 200000000 / PRECISION_6
|
|
37
|
+
'percent_profit': Decimal('99.900994'), # 99900994 / PRECISION_6
|
|
38
|
+
'rollover_fee': Decimal('2.158825'), # 2158825 / PRECISION_6
|
|
39
|
+
'funding_fee': Decimal('3.366384'), # 3366384 / PRECISION_6
|
|
40
|
+
'leverage': Decimal('5'), # 500 / PRECISION_2
|
|
41
|
+
'max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
42
|
+
# 394276779 / PRECISION_6
|
|
43
|
+
'expected_trade_value': Decimal('394.276779'),
|
|
44
|
+
'expected_liq_margin_value': Decimal('25'), # 25000000 / PRECISION_6
|
|
45
|
+
},
|
|
46
|
+
# CASE-3 - change liq margin threshold to 20%
|
|
47
|
+
{
|
|
48
|
+
'liq_margin_threshold_p': Decimal('20'), # 25 (no division needed)
|
|
49
|
+
'collateral': Decimal('200'), # 200000000 / PRECISION_6
|
|
50
|
+
'percent_profit': Decimal('99.900994'), # 99900994 / PRECISION_6
|
|
51
|
+
'rollover_fee': Decimal('2.158825'), # 2158825 / PRECISION_6
|
|
52
|
+
'funding_fee': Decimal('3.366384'), # 3366384 / PRECISION_6
|
|
53
|
+
'leverage': Decimal('5'), # 500 / PRECISION_2
|
|
54
|
+
'max_leverage': Decimal('10'), # 1000 / PRECISION_2
|
|
55
|
+
# 394276779 / PRECISION_6
|
|
56
|
+
'expected_trade_value': Decimal('394.276779'),
|
|
57
|
+
'expected_liq_margin_value': Decimal('20'), # 25000000 / PRECISION_6
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@pytest.mark.parametrize("case", test_cases)
|
|
63
|
+
def test_get_trade_value(case):
|
|
64
|
+
"""Test multiple scenarios for getTradeValue with Pytest."""
|
|
65
|
+
|
|
66
|
+
trade_value, liq_margin_value = getTradeValue(
|
|
67
|
+
liqMarginThresholdP=case['liq_margin_threshold_p'],
|
|
68
|
+
collateral=case['collateral'],
|
|
69
|
+
percentProfit=case['percent_profit'],
|
|
70
|
+
rolloverFee=case['rollover_fee'],
|
|
71
|
+
fundingFee=case['funding_fee'],
|
|
72
|
+
leverage=case['leverage'],
|
|
73
|
+
maxLeverage=case['max_leverage']
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Assert trade value
|
|
77
|
+
assert trade_value == pytest.approx(case['expected_trade_value'], abs=1e-5), \
|
|
78
|
+
f"Trade value failed for case: {case}"
|
|
79
|
+
|
|
80
|
+
# Assert liquidation margin value
|
|
81
|
+
assert liq_margin_value == pytest.approx(case['expected_liq_margin_value'], abs=1e-5), \
|
|
82
|
+
f"Liquidation margin value failed for case: {case}"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
from ostium_python_sdk import OstiumSDK
|
|
5
|
+
from ostium_python_sdk.config import NetworkConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture(scope="module")
|
|
9
|
+
def sdk():
|
|
10
|
+
# Load environment variables
|
|
11
|
+
load_dotenv()
|
|
12
|
+
|
|
13
|
+
rpc_url = os.getenv('RPC_URL')
|
|
14
|
+
if not rpc_url:
|
|
15
|
+
raise ValueError("RPC_URL not found in .env file")
|
|
16
|
+
|
|
17
|
+
# Initialize SDK with testnet config
|
|
18
|
+
config = NetworkConfig.testnet()
|
|
19
|
+
return OstiumSDK(config)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.mark.asyncio
|
|
23
|
+
async def test_max_leverage_validation_for_btc_usd(sdk):
|
|
24
|
+
max_leverage = await sdk.get_pair_max_leverage(0)
|
|
25
|
+
print(f"max_leverage: {max_leverage}")
|
|
26
|
+
|
|
27
|
+
assert max_leverage == pytest.approx(50, abs=1e-5), \
|
|
28
|
+
f"Failed get_pair_max_leverage assertion for BTC/USD"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.asyncio
|
|
32
|
+
async def test_max_leverage_validation_for_eth_usd(sdk):
|
|
33
|
+
max_leverage = await sdk.get_pair_max_leverage(1)
|
|
34
|
+
print(f"max_leverage: {max_leverage}")
|
|
35
|
+
|
|
36
|
+
assert max_leverage == pytest.approx(50, abs=1e-5), \
|
|
37
|
+
f"Failed get_pair_max_leverage assertion for BTC/USD"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.asyncio
|
|
41
|
+
async def test_max_leverage_validation_for_ftse_usd(sdk):
|
|
42
|
+
max_leverage = await sdk.get_pair_max_leverage(14)
|
|
43
|
+
print(f"max_leverage: {max_leverage}")
|
|
44
|
+
|
|
45
|
+
assert max_leverage == pytest.approx(100, abs=1e-5), \
|
|
46
|
+
f"Failed get_pair_max_leverage assertion for FTSE/USD"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pytest.mark.asyncio
|
|
50
|
+
async def test_max_leverage_validation_for_tsla_usd(sdk):
|
|
51
|
+
max_leverage = await sdk.get_pair_max_leverage(22)
|
|
52
|
+
print(f"max_leverage: {max_leverage}")
|
|
53
|
+
|
|
54
|
+
assert max_leverage == pytest.approx(100, abs=1e-5), \
|
|
55
|
+
f"Failed get_pair_max_leverage assertion for TSLA/USD"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
from ostium_python_sdk import OstiumSDK
|
|
5
|
+
from ostium_python_sdk.config import NetworkConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture(scope="module")
|
|
9
|
+
def sdk():
|
|
10
|
+
# Load environment variables
|
|
11
|
+
load_dotenv()
|
|
12
|
+
|
|
13
|
+
rpc_url = os.getenv('RPC_URL')
|
|
14
|
+
if not rpc_url:
|
|
15
|
+
raise ValueError("RPC_URL not found in .env file")
|
|
16
|
+
|
|
17
|
+
# Initialize SDK with testnet config
|
|
18
|
+
config = NetworkConfig.testnet()
|
|
19
|
+
return OstiumSDK(config)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.mark.asyncio
|
|
23
|
+
async def test_overnight_max_leverage_validation_for_btc_usd(sdk):
|
|
24
|
+
overnight_max_leverage = await sdk.get_pair_overnight_max_leverage(0)
|
|
25
|
+
print(f"overnight_max_leverage: {overnight_max_leverage}")
|
|
26
|
+
|
|
27
|
+
assert overnight_max_leverage == pytest.approx(None, abs=1e-5), \
|
|
28
|
+
f"Failed get_pair_overnight_max_leverage assertion for BTC/USD"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.asyncio
|
|
32
|
+
async def test_overnight_max_leverage_validation_for_eth_usd(sdk):
|
|
33
|
+
overnight_max_leverage = await sdk.get_pair_overnight_max_leverage(1)
|
|
34
|
+
print(f"overnight_max_leverage: {overnight_max_leverage}")
|
|
35
|
+
|
|
36
|
+
assert overnight_max_leverage == pytest.approx(None, abs=1e-5), \
|
|
37
|
+
f"Failed get_pair_overnight_max_leverage assertion for BTC/USD"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.asyncio
|
|
41
|
+
async def test_overnight_max_leverage_validation_for_tsla_usd(sdk):
|
|
42
|
+
overnight_max_leverage = await sdk.get_pair_overnight_max_leverage(22)
|
|
43
|
+
print(f"overnight_max_leverage: {overnight_max_leverage}")
|
|
44
|
+
|
|
45
|
+
assert overnight_max_leverage == pytest.approx(10, abs=1e-5), \
|
|
46
|
+
f"Failed get_pair_overnight_max_leverage assertion for TSLA/USD"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/faucet_testnet_abi.py
RENAMED
|
File without changes
|
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/pairs_storage_abi.py
RENAMED
|
File without changes
|
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk/abi/trading_storage_abi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/ostium_python_sdk.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_remove_collateral_from_leverage.py
RENAMED
|
File without changes
|
{ostium_python_sdk-2.0.5 → ostium_python_sdk-2.0.6}/tests/test_remove_collateral_with_collateral.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|