siglab-py 0.1.6__py3-none-any.whl → 0.1.8__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.

@@ -6,6 +6,7 @@ Concrete implementation will:
6
6
  a. Inherit from AnyExchange, thus ccxt Exchange class
7
7
  b. Override ccxt basic functions
8
8
  - load_markets
9
+ - fetch_position
9
10
  - fetch_balance
10
11
  - create_order
11
12
  - update_order
@@ -67,8 +67,9 @@ class DivisiblePosition(Order):
67
67
  self.slices = slices
68
68
  self.wait_fill_threshold_ms = wait_fill_threshold_ms
69
69
  self.multiplier = 1
70
- self.filled_amount = 0
71
- self.average_cost = 0
70
+ self.filled_amount : Union[float, None] = None
71
+ self.average_cost : Union[float, None] = None
72
+ self.pos : Union[float, None] = None # in base ccy, after execution. (Not in USDT or quote ccy, Not in # contracts)
72
73
 
73
74
  self.executions : Dict[str, Dict[str, Any]] = {}
74
75
 
@@ -119,13 +120,11 @@ class DivisiblePosition(Order):
119
120
  def get_filled_amount(self) -> float:
120
121
  # filled_amount is in base ccy
121
122
  filled_amount = sum([ self.executions[order_id]['filled'] * self.multiplier for order_id in self.executions ])
122
- self.filled_amount = filled_amount
123
123
  return filled_amount
124
124
 
125
125
  def get_average_cost(self) -> float:
126
126
  average_cost = sum([ self.executions[order_id]['average'] * self.executions[order_id]['amount'] for order_id in self.executions ])
127
127
  average_cost = average_cost / sum([ self.executions[order_id]['amount'] for order_id in self.executions ])
128
- self.average_cost = average_cost
129
128
  return average_cost
130
129
 
131
130
  def to_dict(self) -> Dict[JSON_SERIALIZABLE_TYPES, JSON_SERIALIZABLE_TYPES]:
@@ -135,6 +134,7 @@ class DivisiblePosition(Order):
135
134
  rv['executions'] = self.executions
136
135
  rv['filled_amount'] = self.filled_amount
137
136
  rv['average_cost'] = self.average_cost
137
+ rv['pos'] = self.pos
138
138
  return rv
139
139
 
140
140
  def execute_positions(
@@ -150,8 +150,6 @@ def execute_positions(
150
150
  _positions = [ position.to_dict() for position in positions ]
151
151
  redis_client.set(name=ordergateway_pending_orders_topic, value=json.dumps(_positions).encode('utf-8'), ex=60*15)
152
152
 
153
- print(f"{ordergateway_pending_orders_topic}: Orders sent {_positions}.")
154
-
155
153
  # Wait for fills
156
154
  fills_received : bool = False
157
155
  while not fills_received:
@@ -165,6 +163,8 @@ def execute_positions(
165
163
  message = message.decode('utf-8')
166
164
  executed_positions = json.loads(message)
167
165
  fills_received = True
166
+
167
+ redis_client.delete(key)
168
168
  break
169
169
 
170
170
  except Exception as loop_err:
@@ -528,6 +528,18 @@ async def execute_one_position(
528
528
  finally:
529
529
  i += 1
530
530
 
531
+ position.filled_amount = position.get_filled_amount()
532
+ position.average_cost = position.get_average_cost()
533
+
534
+ balances = await exchange.fetch_balance() # type: ignore
535
+ if param['default_type']!='spot':
536
+ updated_position = await exchange.fetch_position(symbol=position.ticker) # type: ignore
537
+ amount = updated_position['contracts'] * position.multiplier # in base ccy
538
+ else:
539
+ base_ccy : str = position.ticker.split("/")[0]
540
+ amount = balances[base_ccy]['total']
541
+ position.pos = amount
542
+
531
543
  async def work(
532
544
  param : Dict,
533
545
  exchange : AnyExchange,
@@ -581,7 +593,7 @@ async def work(
581
593
 
582
594
  i = 0
583
595
  for position in positions:
584
- log(f"{i} {position.ticker}, {position.side} # executions: {len(position.get_executions())}, filled_amount: {position.get_filled_amount()}, average_cost: {position.get_average_cost()}, order_dispatch_elapsed_ms: {order_dispatch_elapsed_ms}")
596
+ log(f"{i} {position.ticker}, {position.side} # executions: {len(position.get_executions())}, filled_amount: {position.filled_amount}, average_cost: {position.average_cost}, pos: {position.pos}, order_dispatch_elapsed_ms: {order_dispatch_elapsed_ms}")
585
597
  i += 1
586
598
 
587
599
  start = time.time()
@@ -12,7 +12,7 @@ from ccxt.deribit import deribit
12
12
  from ccxt.base.exchange import Exchange
13
13
 
14
14
  # @unittest.skip("Skip all integration tests.")
15
- class MarketDataGizmoTests(unittest.TestCase):
15
+ class MarketDataUtilTests(unittest.TestCase):
16
16
 
17
17
  def test_fetch_candles_yahoo(self):
18
18
  start_date : datetime = datetime(2024, 1,1)
@@ -89,16 +89,11 @@ class MarketDataGizmoTests(unittest.TestCase):
89
89
  param = {
90
90
  'apiKey' : None,
91
91
  'secret' : None,
92
- 'password' : None, # Other exchanges dont require this! This is saved in exchange.password!
92
+ 'password' : None,
93
93
  'subaccount' : None,
94
94
  'rateLimit' : 100, # In ms
95
95
  'options' : {
96
- 'defaultType': 'swap', # Should test linear instead
97
- 'leg_room_bps' : 5,
98
- 'trade_fee_bps' : 3,
99
-
100
- 'list_ts_field' : 'listTime' # list_ts_field: Response field in exchange.markets[symbol] to indiate timestamp of symbol's listing date in ms. For bybit, markets['launchTime'] is list date. For okx, it's markets['listTime'].
101
- }
96
+ 'defaultType': 'swap' }
102
97
  }
103
98
 
104
99
  exchange : Exchange = okx(param)
@@ -0,0 +1,45 @@
1
+ import unittest
2
+ from typing import List
3
+ from pathlib import Path
4
+
5
+ from util.analytic_util import compute_candles_stats
6
+
7
+ import pandas as pd
8
+
9
+ '''
10
+ Manual checks against for example Tradingview here: \siglab\siglab_py\tests\manual
11
+ '''
12
+
13
+ # @unittest.skip("Skip all integration tests.")
14
+ class AnalyticUtilTests(unittest.TestCase):
15
+
16
+ def test_compute_candle_stats(self):
17
+ '''
18
+ Folder structure:
19
+ \ siglab
20
+ \ siglab_py <-- python project root
21
+ \ sigab_py
22
+ __init__.py
23
+ \ util
24
+ __init__.py
25
+ market_data_util.py
26
+ \ tests
27
+ \ unit
28
+ __init__.py
29
+ analytic_util_tests.py <-- Tests here
30
+
31
+ \ siglab_rs <-- Rust project root
32
+ \ data <-- Data files here!
33
+ '''
34
+ data_dir = Path(__file__).parent.parent.parent.parent / "data"
35
+ csv_path = data_dir / "sample_btc_candles.csv"
36
+ pd_candles : pd.DataFrame = pd.read_csv(csv_path)
37
+ compute_candles_stats(
38
+ pd_candles=pd_candles,
39
+ boillenger_std_multiples=2,
40
+ sliding_window_how_many_candles=20,
41
+ pypy_compat=True
42
+ )
43
+
44
+ expected_columns : List[str] = ['exchange', 'symbol', 'timestamp_ms', 'open', 'high', 'low', 'close', 'volume', 'datetime', 'datetime_utc', 'year', 'month', 'day', 'hour', 'minute', 'dayofweek', 'pct_chg_on_close', 'candle_height', 'is_green', 'pct_change_close', 'sma_short_periods', 'sma_long_periods', 'ema_short_periods', 'ema_long_periods', 'ema_close', 'std', 'ema_volume_short_periods', 'ema_volume_long_periods', 'max_short_periods', 'max_long_periods', 'idmax_short_periods', 'idmax_long_periods', 'min_short_periods', 'min_long_periods', 'idmin_short_periods', 'idmin_long_periods', 'h_l', 'h_pc', 'l_pc', 'tr', 'atr', 'hurst_exp', 'boillenger_upper', 'boillenger_lower', 'boillenger_channel_height', 'boillenger_upper_agg', 'boillenger_lower_agg', 'boillenger_channel_height_agg', 'aggressive_up', 'aggressive_up_index', 'aggressive_up_candle_height', 'aggressive_up_candle_high', 'aggressive_up_candle_low', 'aggressive_down', 'aggressive_down_index', 'aggressive_down_candle_height', 'aggressive_down_candle_high', 'aggressive_down_candle_low', 'fvg_low', 'fvg_high', 'fvg_gap', 'fvg_mitigated', 'close_delta', 'close_delta_percent', 'up', 'down', 'rsi', 'ema_rsi', 'typical_price', 'money_flow', 'money_flow_positive', 'money_flow_negative', 'positive_flow_sum', 'negative_flow_sum', 'money_flow_ratio', 'mfi', 'macd', 'signal', 'macd_minus_signal', 'fib_618_short_periods', 'fib_618_long_periods', 'gap_close_vs_ema', 'close_above_or_below_ema', 'close_vs_ema_inflection']
45
+ assert(pd_candles.columns.to_list()==expected_columns)
@@ -3,6 +3,11 @@ from typing import Union, Dict
3
3
  '''
4
4
  https://gist.github.com/raphaelgabbarelli/bc5a41d93789046f9c71e4685f1463e7
5
5
  https://www.youtube.com/watch?v=CFEYKrP0vxs
6
+
7
+ If boto3 import complains: AttributeError: module 'lib' has no attribute 'X509_V_FLAG_CB_ISSUER_CHECK'
8
+ python3 -m pip install pip --upgrade
9
+ pip install pyopenssl --upgrade
10
+ https://stackoverflow.com/questions/73830524/attributeerror-module-lib-has-no-attribute-x509-v-flag-cb-issuer-check
6
11
  '''
7
12
  import boto3
8
13
  import base64
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siglab-py
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Market data fetches, TA calculations and generic order gateway.
5
5
  Author: r0bbarh00d
6
6
  Author-email: r0bbarh00d <r0bbarh00d@gmail.com>
@@ -1,7 +1,7 @@
1
1
  siglab_py/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  siglab_py/constants.py,sha256=YGNdEsWtQ99V2oltaynZTjM8VIboSfyIjDXJKSlhv4U,132
3
3
  siglab_py/exchanges/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- siglab_py/exchanges/any_exchange.py,sha256=blsB_itXEcr8-DxT4DI5n9v9htJGbU0OsW68fx6pIgo,727
4
+ siglab_py/exchanges/any_exchange.py,sha256=pnSAatOzUIgwY9iPa5XR5xF_C5VIXAWi_uAhjvBP8bQ,749
5
5
  siglab_py/market_data_providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  siglab_py/market_data_providers/aggregated_orderbook_provider.py,sha256=uN6oD6PqbfnkPKVzKF_GfSEuXdtmv0lFTB-yg9gRYcI,23234
7
7
  siglab_py/market_data_providers/candles_provider.py,sha256=fqHJjlECsBiBlpgyywrc4gTgxiROPNzZM8KxQBB5cOg,14139
@@ -10,20 +10,21 @@ siglab_py/market_data_providers/deribit_options_expiry_provider.py,sha256=mP-508
10
10
  siglab_py/market_data_providers/orderbooks_provider.py,sha256=cBp-HYCups2Uiwzw0SaUwxrg4unJvnm2TDqIK8f4hUg,15674
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=RWngzDnqsE_7LUqvRcDopTHxUNYKrA-FF_0A-IfJv90,6419
13
+ siglab_py/ordergateway/client.py,sha256=BndmyQkAtPSEXQP9vR8ySiPIkODjuf0-LOwnsFFPPhg,6508
14
14
  siglab_py/ordergateway/encrypt_keys_util.py,sha256=-qi87db8To8Yf1WS1Q_Cp2Ya7ZqgWlRqSHfNXCM7wE4,1339
15
- siglab_py/ordergateway/gateway.py,sha256=xlTThsNRRHYWilpc3zpAcYC2nxG4crfpDY8Refbnl64,30038
15
+ siglab_py/ordergateway/gateway.py,sha256=n1tfKsSujdyygyV3fYGy56CGXMT1Y_6BFuOsXesG3bU,30589
16
16
  siglab_py/ordergateway/test_ordergateway.py,sha256=DH4djEZeWZr69lTx_xG9_N8S_E2wAG4S3430VisU5w4,3805
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
- siglab_py/tests/integration/market_data_util_tests.py,sha256=_UyOMTTBW1VJ7rroyESoxmdhBCQzWSV2A14tAjV9J5U,5634
19
+ siglab_py/tests/integration/market_data_util_tests.py,sha256=HFESIXEdQmrbDV3DvLiDLq0iE-4itysxSFur_Th4jjE,5207
20
20
  siglab_py/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ siglab_py/tests/unit/analytic_util_tests.py,sha256=-FGj-cWdIZ_WZQqQCIpDLRSv5TlJIG81fHyBlWuAm1U,2961
21
22
  siglab_py/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  siglab_py/util/analytic_util.py,sha256=QLabbEMqM4rKKH2PE_LqxIyo-BUdCRhkLybLATBImcc,43438
23
- siglab_py/util/aws_util.py,sha256=x_duGDXJ6sO0wVpoRVDTMxECag7feA7zOwZweVLGl_w,2251
24
+ siglab_py/util/aws_util.py,sha256=KGmjHrr1rpnnxr33nXHNzTul4tvyyxl9p6gpwNv0Ygc,2557
24
25
  siglab_py/util/market_data_util.py,sha256=3qTq71xGvQXj0ORKJV50IN5FP_mCBF_gvdmlPyhdyco,16439
25
26
  siglab_py/util/retry_util.py,sha256=mxYuRFZRZoaQQjENcwPmxhxixtd1TFvbxIdPx4RwfRc,743
26
- siglab_py-0.1.6.dist-info/METADATA,sha256=-5cCWoewOwKri1IrLJG7rIeff4vbZpqDUQtQnxiTlDU,1096
27
- siglab_py-0.1.6.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
28
- siglab_py-0.1.6.dist-info/top_level.txt,sha256=AbD4VR9OqmMOGlMJLkAVPGQMtUPIQv0t1BF5xmcLJSk,10
29
- siglab_py-0.1.6.dist-info/RECORD,,
27
+ siglab_py-0.1.8.dist-info/METADATA,sha256=QqYYIHR02shHkYxd9X4vBgxwhhp_6eoYEctTN-rUgpk,1096
28
+ siglab_py-0.1.8.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
29
+ siglab_py-0.1.8.dist-info/top_level.txt,sha256=AbD4VR9OqmMOGlMJLkAVPGQMtUPIQv0t1BF5xmcLJSk,10
30
+ siglab_py-0.1.8.dist-info/RECORD,,