siglab-py 0.1.12__py3-none-any.whl → 0.1.13__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.
Potentially problematic release.
This version of siglab-py might be problematic. Click here for more details.
- siglab_py/market_data_providers/orderbooks_provider.py +18 -0
- siglab_py/ordergateway/client.py +7 -1
- siglab_py/ordergateway/gateway.py +28 -2
- siglab_py/ordergateway/test_ordergateway.py +3 -0
- {siglab_py-0.1.12.dist-info → siglab_py-0.1.13.dist-info}/METADATA +1 -1
- {siglab_py-0.1.12.dist-info → siglab_py-0.1.13.dist-info}/RECORD +8 -8
- {siglab_py-0.1.12.dist-info → siglab_py-0.1.13.dist-info}/WHEEL +0 -0
- {siglab_py-0.1.12.dist-info → siglab_py-0.1.13.dist-info}/top_level.txt +0 -0
|
@@ -290,6 +290,9 @@ async def _handle_ticker(
|
|
|
290
290
|
task : ThreadTask
|
|
291
291
|
):
|
|
292
292
|
exchange = await instantiate_exhange(exchange_name=exchange_name, old_exchange=None)
|
|
293
|
+
|
|
294
|
+
asyncio.create_task(send_heartbeat(exchange))
|
|
295
|
+
|
|
293
296
|
ob = OrderBook(ticker=ticker, exchange_name=exchange_name)
|
|
294
297
|
candles_publish_topic = candles_publish_topic.replace("$SYMBOL$", ticker)
|
|
295
298
|
candles_publish_topic = candles_publish_topic.replace("$EXCHANGE$", exchange_name)
|
|
@@ -318,6 +321,21 @@ async def _handle_ticker(
|
|
|
318
321
|
exchange = await instantiate_exhange(exchange_name=exchange_name, old_exchange=exchange) # type: ignore Otherwise, Error: Argument of type "Coroutine[Any, Any, Exchange] | Exchange" cannot be assigned to parameter "old_exchange" of type "Exchange | None" in function "instantiate_exhange"
|
|
319
322
|
ob = OrderBook(ticker=ticker, exchange_name=exchange_name)
|
|
320
323
|
|
|
324
|
+
async def send_heartbeat(exchange):
|
|
325
|
+
|
|
326
|
+
await asyncio.sleep(10)
|
|
327
|
+
|
|
328
|
+
while True:
|
|
329
|
+
try:
|
|
330
|
+
first_ws_url = next(iter(exchange.clients))
|
|
331
|
+
client = exchange.clients[first_ws_url]
|
|
332
|
+
message = exchange.ping(client)
|
|
333
|
+
await client.send(message)
|
|
334
|
+
log('Heartbeat sent')
|
|
335
|
+
except Exception as hb_error:
|
|
336
|
+
log(f'Failed to send heartbeat: {hb_error}')
|
|
337
|
+
finally:
|
|
338
|
+
await asyncio.sleep(30)
|
|
321
339
|
|
|
322
340
|
async def main():
|
|
323
341
|
parse_args()
|
siglab_py/ordergateway/client.py
CHANGED
|
@@ -32,6 +32,7 @@ class Order:
|
|
|
32
32
|
amount : float,
|
|
33
33
|
order_type : str, # market/limit
|
|
34
34
|
leg_room_bps : float = 0,
|
|
35
|
+
reduce_only : bool = False,
|
|
35
36
|
fees_ccy : Union[str, None] = None
|
|
36
37
|
) -> None:
|
|
37
38
|
self.ticker = ticker
|
|
@@ -39,6 +40,7 @@ class Order:
|
|
|
39
40
|
self.amount = amount
|
|
40
41
|
self.order_type = order_type.strip().lower()
|
|
41
42
|
self.leg_room_bps = leg_room_bps
|
|
43
|
+
self.reduce_only = reduce_only
|
|
42
44
|
self.fees_ccy = fees_ccy
|
|
43
45
|
|
|
44
46
|
def to_dict(self) -> Dict[JSON_SERIALIZABLE_TYPES, JSON_SERIALIZABLE_TYPES]:
|
|
@@ -48,6 +50,7 @@ class Order:
|
|
|
48
50
|
"amount" : self.amount,
|
|
49
51
|
"order_type" : self.order_type,
|
|
50
52
|
"leg_room_bps" : self.leg_room_bps,
|
|
53
|
+
"reduce_only" : self.reduce_only,
|
|
51
54
|
"fees_ccy" : self.fees_ccy
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -63,11 +66,12 @@ class DivisiblePosition(Order):
|
|
|
63
66
|
amount : float,
|
|
64
67
|
order_type : str, # market/limit
|
|
65
68
|
leg_room_bps : float,
|
|
69
|
+
reduce_only : bool = False,
|
|
66
70
|
fees_ccy : Union[str, None] = None,
|
|
67
71
|
slices : int = 1,
|
|
68
72
|
wait_fill_threshold_ms : float = -1
|
|
69
73
|
) -> None:
|
|
70
|
-
super().__init__(ticker, side, amount, order_type, leg_room_bps, fees_ccy)
|
|
74
|
+
super().__init__(ticker, side, amount, order_type, leg_room_bps, reduce_only, fees_ccy)
|
|
71
75
|
self.slices = slices
|
|
72
76
|
self.wait_fill_threshold_ms = wait_fill_threshold_ms
|
|
73
77
|
self.multiplier = 1
|
|
@@ -91,6 +95,7 @@ class DivisiblePosition(Order):
|
|
|
91
95
|
side=self.side,
|
|
92
96
|
amount=slice_amount_in_base_ccy,
|
|
93
97
|
leg_room_bps=self.leg_room_bps,
|
|
98
|
+
reduce_only=self.reduce_only,
|
|
94
99
|
fees_ccy=self.fees_ccy,
|
|
95
100
|
order_type=self.order_type)
|
|
96
101
|
|
|
@@ -101,6 +106,7 @@ class DivisiblePosition(Order):
|
|
|
101
106
|
side=self.side,
|
|
102
107
|
amount=remaining_amount_in_base_ccy,
|
|
103
108
|
leg_room_bps=self.leg_room_bps,
|
|
109
|
+
reduce_only=self.reduce_only,
|
|
104
110
|
fees_ccy=self.fees_ccy,
|
|
105
111
|
order_type=self.order_type)
|
|
106
112
|
|
|
@@ -184,7 +184,8 @@ param : Dict = {
|
|
|
184
184
|
"incoming_orders_topic_regex" : r"ordergateway_pending_orders_$GATEWAY_ID$",
|
|
185
185
|
"executions_publish_topic" : r"ordergateway_executions_$GATEWAY_ID$",
|
|
186
186
|
|
|
187
|
-
"
|
|
187
|
+
"default_fees_ccy" : None,
|
|
188
|
+
"loop_freq_ms" : 500, # reduce this if you need trade faster
|
|
188
189
|
|
|
189
190
|
'mds' : {
|
|
190
191
|
'topics' : {
|
|
@@ -261,6 +262,9 @@ def parse_args():
|
|
|
261
262
|
parser.add_argument("--default_type", help="default_type: spot, linear, inverse, futures ...etc", default='linear')
|
|
262
263
|
parser.add_argument("--rate_limit_ms", help="rate_limit_ms: Check your exchange rules", default=100)
|
|
263
264
|
|
|
265
|
+
parser.add_argument("--default_fees_ccy", help="If you're trading crypto, CEX fees USDT, DEX fees USDC in many cases. Default None, in which case gateway won't aggregatge fees from executions for you.", default=None)
|
|
266
|
+
parser.add_argument("--loop_freq_ms", help="Loop delays. Reduce this if you want to trade faster.", default=500)
|
|
267
|
+
|
|
264
268
|
parser.add_argument("--encrypt_decrypt_with_aws_kms", help="Y or N. If encrypt_decrypt_with_aws_kms=N, pass in apikey, secret and passphrase unencrypted (Not recommended, for testing only). If Y, they will be decrypted using AMS KMS key.", default='N')
|
|
265
269
|
parser.add_argument("--aws_kms_key_id", help="AWS KMS key ID", default=None)
|
|
266
270
|
parser.add_argument("--apikey", help="Exchange apikey", default=None)
|
|
@@ -280,6 +284,8 @@ def parse_args():
|
|
|
280
284
|
|
|
281
285
|
param['default_type'] = args.default_type
|
|
282
286
|
param['rate_limit_ms'] = int(args.rate_limit_ms)
|
|
287
|
+
param['default_fees_ccy'] = args.default_fees_ccy
|
|
288
|
+
param['loop_freq_ms'] = int(args.loop_freq_ms)
|
|
283
289
|
|
|
284
290
|
if args.encrypt_decrypt_with_aws_kms:
|
|
285
291
|
if args.encrypt_decrypt_with_aws_kms=='Y':
|
|
@@ -422,6 +428,22 @@ async def watch_orders_task(
|
|
|
422
428
|
|
|
423
429
|
await asyncio.sleep(int(param['loop_freq_ms']/1000))
|
|
424
430
|
|
|
431
|
+
async def send_heartbeat(exchange):
|
|
432
|
+
|
|
433
|
+
await asyncio.sleep(10)
|
|
434
|
+
|
|
435
|
+
while True:
|
|
436
|
+
try:
|
|
437
|
+
first_ws_url = next(iter(exchange.clients))
|
|
438
|
+
client = exchange.clients[first_ws_url]
|
|
439
|
+
message = exchange.ping(client)
|
|
440
|
+
await client.send(message)
|
|
441
|
+
log('Heartbeat sent')
|
|
442
|
+
except Exception as hb_error:
|
|
443
|
+
log(f'Failed to send heartbeat: {hb_error}')
|
|
444
|
+
finally:
|
|
445
|
+
await asyncio.sleep(30)
|
|
446
|
+
|
|
425
447
|
async def execute_one_position(
|
|
426
448
|
exchange : AnyExchange,
|
|
427
449
|
position : DivisiblePosition,
|
|
@@ -674,10 +696,12 @@ async def work(
|
|
|
674
696
|
|
|
675
697
|
# This is how we avoid reprocess same message twice. We check message hash and cache it.
|
|
676
698
|
processed_hash_queue = deque(maxlen=10)
|
|
677
|
-
|
|
699
|
+
|
|
678
700
|
executions : Dict[str, Dict[str, Any]] = {}
|
|
679
701
|
asyncio.create_task(watch_orders_task(exchange, executions))
|
|
680
702
|
|
|
703
|
+
asyncio.create_task(send_heartbeat(exchange))
|
|
704
|
+
|
|
681
705
|
while True:
|
|
682
706
|
try:
|
|
683
707
|
keys = redis_client.keys()
|
|
@@ -701,6 +725,8 @@ async def work(
|
|
|
701
725
|
amount=order['amount'],
|
|
702
726
|
order_type=order['order_type'],
|
|
703
727
|
leg_room_bps=order['leg_room_bps'],
|
|
728
|
+
reduce_only=order['reduce_only'],
|
|
729
|
+
fees_ccy=order['fees_ccy'] if 'fees_ccy' in order else param['default_fees_ccy'],
|
|
704
730
|
slices=order['slices'],
|
|
705
731
|
wait_fill_threshold_ms=order['wait_fill_threshold_ms']
|
|
706
732
|
)
|
|
@@ -69,6 +69,7 @@ if __name__ == '__main__':
|
|
|
69
69
|
side = 'buy',
|
|
70
70
|
amount = 10,
|
|
71
71
|
leg_room_bps = 5,
|
|
72
|
+
reduce_only=False,
|
|
72
73
|
order_type = 'limit',
|
|
73
74
|
slices=5,
|
|
74
75
|
wait_fill_threshold_ms=15000
|
|
@@ -81,6 +82,7 @@ if __name__ == '__main__':
|
|
|
81
82
|
side = 'buy',
|
|
82
83
|
amount = 10,
|
|
83
84
|
leg_room_bps = 5,
|
|
85
|
+
reduce_only=False,
|
|
84
86
|
order_type = 'limit',
|
|
85
87
|
slices=5,
|
|
86
88
|
wait_fill_threshold_ms=15000
|
|
@@ -93,6 +95,7 @@ if __name__ == '__main__':
|
|
|
93
95
|
side = 'sell',
|
|
94
96
|
amount = 0.01,
|
|
95
97
|
leg_room_bps = 5,
|
|
98
|
+
reduce_only=False,
|
|
96
99
|
order_type = 'limit',
|
|
97
100
|
slices=1,
|
|
98
101
|
wait_fill_threshold_ms=60000
|
|
@@ -7,13 +7,13 @@ siglab_py/market_data_providers/aggregated_orderbook_provider.py,sha256=FZRobEBN
|
|
|
7
7
|
siglab_py/market_data_providers/candles_provider.py,sha256=fqHJjlECsBiBlpgyywrc4gTgxiROPNzZM8KxQBB5cOg,14139
|
|
8
8
|
siglab_py/market_data_providers/candles_ta_provider.py,sha256=uiAhbEZZdTF-YulBHpSLwabos5LHCKU91NTiTmpUc0w,12001
|
|
9
9
|
siglab_py/market_data_providers/deribit_options_expiry_provider.py,sha256=e9Ee8TmC8pXaid8-jouSLKIpuW6_JBBgwRTieI665yQ,8684
|
|
10
|
-
siglab_py/market_data_providers/orderbooks_provider.py,sha256=
|
|
10
|
+
siglab_py/market_data_providers/orderbooks_provider.py,sha256=olt-3LIkoyzQWfNNQRhJtKibLbkTutt_q_rCCTM7i1g,16216
|
|
11
11
|
siglab_py/market_data_providers/test_provider.py,sha256=wBLCgcWjs7FGZJXWsNyn30lkOLa_cgpuvqRakMC0wbA,2221
|
|
12
12
|
siglab_py/ordergateway/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
siglab_py/ordergateway/client.py,sha256=
|
|
13
|
+
siglab_py/ordergateway/client.py,sha256=4X5rR_jebh7rkw5ANGMHSmoONXbFHzxX5SPt6ZzeOdA,9257
|
|
14
14
|
siglab_py/ordergateway/encrypt_keys_util.py,sha256=-qi87db8To8Yf1WS1Q_Cp2Ya7ZqgWlRqSHfNXCM7wE4,1339
|
|
15
|
-
siglab_py/ordergateway/gateway.py,sha256=
|
|
16
|
-
siglab_py/ordergateway/test_ordergateway.py,sha256=
|
|
15
|
+
siglab_py/ordergateway/gateway.py,sha256=9y60GXrvRnzOO28rhsa4mBV-eV0vetnBAj1Gr3azCFQ,36747
|
|
16
|
+
siglab_py/ordergateway/test_ordergateway.py,sha256=_Gz2U_VqljogGWqGyNDYYls1INqUiig9veyPttfGRpg,3901
|
|
17
17
|
siglab_py/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
18
|
siglab_py/tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
siglab_py/tests/integration/market_data_util_tests.py,sha256=HFESIXEdQmrbDV3DvLiDLq0iE-4itysxSFur_Th4jjE,5207
|
|
@@ -24,7 +24,7 @@ siglab_py/util/analytic_util.py,sha256=QLabbEMqM4rKKH2PE_LqxIyo-BUdCRhkLybLATBIm
|
|
|
24
24
|
siglab_py/util/aws_util.py,sha256=KGmjHrr1rpnnxr33nXHNzTul4tvyyxl9p6gpwNv0Ygc,2557
|
|
25
25
|
siglab_py/util/market_data_util.py,sha256=3qTq71xGvQXj0ORKJV50IN5FP_mCBF_gvdmlPyhdyco,16439
|
|
26
26
|
siglab_py/util/retry_util.py,sha256=mxYuRFZRZoaQQjENcwPmxhxixtd1TFvbxIdPx4RwfRc,743
|
|
27
|
-
siglab_py-0.1.
|
|
28
|
-
siglab_py-0.1.
|
|
29
|
-
siglab_py-0.1.
|
|
30
|
-
siglab_py-0.1.
|
|
27
|
+
siglab_py-0.1.13.dist-info/METADATA,sha256=K059FaL9RhsHiKNV3rKYnOArB9K93ePUg8r39ZIPJrQ,1097
|
|
28
|
+
siglab_py-0.1.13.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
29
|
+
siglab_py-0.1.13.dist-info/top_level.txt,sha256=AbD4VR9OqmMOGlMJLkAVPGQMtUPIQv0t1BF5xmcLJSk,10
|
|
30
|
+
siglab_py-0.1.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|