siglab-py 0.5.36__tar.gz → 0.5.38__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.

Potentially problematic release.


This version of siglab-py might be problematic. Click here for more details.

Files changed (43) hide show
  1. {siglab_py-0.5.36 → siglab_py-0.5.38}/PKG-INFO +1 -1
  2. {siglab_py-0.5.36 → siglab_py-0.5.38}/pyproject.toml +1 -1
  3. {siglab_py-0.5.36 → siglab_py-0.5.38}/setup.cfg +1 -1
  4. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/unit/analytic_util_tests.py +28 -3
  5. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/analytic_util.py +78 -10
  6. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/notification_util.py +1 -1
  7. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py.egg-info/PKG-INFO +1 -1
  8. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/__init__.py +0 -0
  9. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/constants.py +0 -0
  10. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/exchanges/__init__.py +0 -0
  11. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/exchanges/any_exchange.py +0 -0
  12. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/exchanges/futubull.py +0 -0
  13. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/__init__.py +0 -0
  14. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/aggregated_orderbook_provider.py +0 -0
  15. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/candles_provider.py +0 -0
  16. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/candles_ta_provider.py +0 -0
  17. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py +0 -0
  18. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/deribit_options_expiry_provider.py +0 -0
  19. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py +0 -0
  20. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/orderbooks_provider.py +0 -0
  21. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/test_provider.py +0 -0
  22. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/market_data_providers/tg_monitor.py +0 -0
  23. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/ordergateway/__init__.py +0 -0
  24. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/ordergateway/client.py +0 -0
  25. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/ordergateway/encrypt_keys_util.py +0 -0
  26. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/ordergateway/gateway.py +0 -0
  27. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/ordergateway/test_ordergateway.py +0 -0
  28. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/__init__.py +0 -0
  29. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/integration/__init__.py +0 -0
  30. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/integration/market_data_util_tests.py +0 -0
  31. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/unit/__init__.py +0 -0
  32. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/unit/market_data_util_tests.py +0 -0
  33. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/tests/unit/trading_util_tests.py +0 -0
  34. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/__init__.py +0 -0
  35. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/aws_util.py +0 -0
  36. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/market_data_util.py +0 -0
  37. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/retry_util.py +0 -0
  38. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/slack_notification_util.py +0 -0
  39. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py/util/trading_util.py +0 -0
  40. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py.egg-info/SOURCES.txt +0 -0
  41. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py.egg-info/dependency_links.txt +0 -0
  42. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py.egg-info/requires.txt +0 -0
  43. {siglab_py-0.5.36 → siglab_py-0.5.38}/siglab_py.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siglab_py
3
- Version: 0.5.36
3
+ Version: 0.5.38
4
4
  Summary: Market data fetches, TA calculations and generic order gateway.
5
5
  Author: r0bbarh00d
6
6
  Author-email: r0bbarh00d <r0bbarh00d@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "siglab_py"
7
- version = "0.5.36"
7
+ version = "0.5.38"
8
8
  description = "Market data fetches, TA calculations and generic order gateway."
9
9
  authors = [{name = "r0bbarh00d", email = "r0bbarh00d@gmail.com"}]
10
10
  license = {text = "MIT"}
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = siglab_py
3
- version = 0.5.36
3
+ version = 0.5.38
4
4
  description = Market data fetches, TA calculations and generic order gateway.
5
5
  author = r0bbarh00d
6
6
  author_email = r0bbarh00d@gmail.com
@@ -2,7 +2,7 @@ import unittest
2
2
  from typing import List
3
3
  from pathlib import Path
4
4
 
5
- from util.analytic_util import compute_candles_stats
5
+ from util.analytic_util import compute_candles_stats, lookup_fib_target
6
6
 
7
7
  import pandas as pd
8
8
 
@@ -38,7 +38,7 @@ class AnalyticUtilTests(unittest.TestCase):
38
38
  pd_candles=pd_candles,
39
39
  boillenger_std_multiples=2,
40
40
  sliding_window_how_many_candles=20,
41
- pypy_compat=True
41
+ pypy_compat=True # Slopes calculation? Set pypy_compat to False
42
42
  )
43
43
 
44
44
  expected_columns : List[str] = [
@@ -78,4 +78,29 @@ class AnalyticUtilTests(unittest.TestCase):
78
78
  missing_columns = [ expected for expected in expected_columns if expected not in pd_candles.columns.to_list() ]
79
79
  unexpected_columns = [ actual for actual in pd_candles.columns.to_list() if actual not in expected_columns ]
80
80
 
81
- assert(pd_candles.columns.to_list()==expected_columns)
81
+ assert(pd_candles.columns.to_list()==expected_columns)
82
+
83
+ def test_lookup_fib_target(self):
84
+ data_dir = Path(__file__).parent.parent.parent.parent / "data"
85
+ csv_path = data_dir / "sample_btc_candles.csv"
86
+ pd_candles : pd.DataFrame = pd.read_csv(csv_path)
87
+ target_fib_level : float = 0.618
88
+ compute_candles_stats(
89
+ pd_candles=pd_candles,
90
+ boillenger_std_multiples=2,
91
+ sliding_window_how_many_candles=20,
92
+ target_fib_level=target_fib_level,
93
+ pypy_compat=True # Slopes calculation? Set pypy_compat to False
94
+ )
95
+
96
+ last_row = pd_candles.iloc[-1]
97
+ result = lookup_fib_target(
98
+ row=last_row,
99
+ pd_candles=pd_candles,
100
+ target_fib_level=target_fib_level
101
+ )
102
+ if result:
103
+ assert(result['short_periods']['min']<result['short_periods']['fib_target']<result['short_periods']['max'])
104
+ assert(result['long_periods']['min']<result['long_periods']['fib_target']<result['long_periods']['max'])
105
+
106
+
@@ -83,14 +83,15 @@ def trend_from_lows(series: np.ndarray) -> float:
83
83
  '''
84
84
  compute_candles_stats will calculate typical/basic technical indicators using in many trading strategies:
85
85
  a. Basic SMA/EMAs (And slopes)
86
- b. ATR
87
- c. Boillenger bands (Yes incorrect spelling sorry)
88
- d. FVG
89
- e. Hurst Exponent
90
- f. RSI, MFI
91
- g. MACD
92
- h. Fibonacci
93
- i. Inflections points: where 'close' crosses EMA from above or below.
86
+ b. EMA crosses
87
+ c. ATR
88
+ d. Boillenger bands (Yes incorrect spelling sorry)
89
+ e. FVG
90
+ f. Hurst Exponent
91
+ g. RSI, MFI
92
+ h. MACD
93
+ i. Fibonacci
94
+ j. Inflections points: where 'close' crosses EMA from above or below.
94
95
 
95
96
  Parameters:
96
97
  a. boillenger_std_multiples: For boillenger upper and lower calc
@@ -167,6 +168,8 @@ def compute_candles_stats(
167
168
  pd_candles['annualized_volatility'] = (
168
169
  pd_candles['interval_historical_volatility'] * annualization_factor
169
170
  )
171
+
172
+ Why log return? Trading Dude https://python.plainenglish.io/stop-using-percentage-returns-logarithmic-returns-explained-with-code-64a4634b883a
170
173
  '''
171
174
  pd_candles['log_return'] = np.log(pd_candles['close'] / pd_candles['close'].shift(1))
172
175
  pd_candles['interval_hist_vol'] = pd_candles['log_return'].rolling(window=sliding_window_how_many_candles).std()
@@ -431,8 +434,11 @@ def compute_candles_stats(
431
434
 
432
435
  pd_candles['fvg_mitigated'] = pd_candles.apply(lambda row: compute_fvg_mitigated(row, pd_candles), axis=1)
433
436
 
434
-
435
- # RSI - https://www.youtube.com/watch?v=G9oUTi-PI18&t=809s
437
+ '''
438
+ RSI
439
+ Divergences from Bybit Learn https://www.youtube.com/watch?v=G9oUTi-PI18&t=809s
440
+ RSI Reversals from BK Traders https://www.youtube.com/watch?v=MvkbrHjiQlI
441
+ '''
436
442
  pd_candles.loc[:,'close_delta'] = pd_candles['close'].diff()
437
443
  pd_candles.loc[:,'close_delta_percent'] = pd_candles['close'].pct_change()
438
444
  lo_up = pd_candles['close_delta'].clip(lower=0)
@@ -606,6 +612,68 @@ def compute_candles_stats(
606
612
  'close_vs_ema_inflection'
607
613
  ] = np.sign(pd_candles['close'] - pd_candles['ema_long_periods'])
608
614
 
615
+ def lookup_fib_target(
616
+ row,
617
+ pd_candles,
618
+ target_fib_level : float = 0.618
619
+ ) -> Union[Dict, None]:
620
+ if row is None:
621
+ return None
622
+
623
+ fib_target_short_periods = None
624
+ fib_target_long_periods = None
625
+
626
+ max_short_periods = row['max_short_periods']
627
+ idmax_short_periods = int(row['idmax_short_periods']) if not math.isnan(row['idmax_short_periods']) else None
628
+ max_long_periods = row['max_long_periods']
629
+ idmax_long_periods = int(row['idmax_long_periods']) if not math.isnan(row['idmax_long_periods']) else None
630
+
631
+ min_short_periods = row['min_short_periods']
632
+ idmin_short_periods = int(row['idmin_short_periods']) if not math.isnan(row['idmin_short_periods']) else None
633
+ min_long_periods = row['min_long_periods']
634
+ idmin_long_periods = int(row['idmin_long_periods']) if not math.isnan(row['idmin_long_periods']) else None
635
+
636
+ if idmax_short_periods and idmin_short_periods and idmax_short_periods>0 and idmin_short_periods>0:
637
+ if idmax_short_periods>idmin_short_periods and idmax_short_periods < len(pd_candles):
638
+ # Falling from prev peak
639
+ last_peak = pd_candles.iloc[idmax_short_periods]
640
+ fib_target_short_periods = last_peak[f'fib_{target_fib_level}_short_periods'] if not math.isnan(last_peak[f'fib_{target_fib_level}_short_periods']) else None
641
+
642
+ else:
643
+ # Bouncing from prev bottom
644
+ if idmin_short_periods < len(pd_candles):
645
+ last_bottom = pd_candles.iloc[idmin_short_periods]
646
+ fib_target_short_periods = last_bottom[f'fib_{target_fib_level}_short_periods'] if not math.isnan(last_bottom[f'fib_{target_fib_level}_short_periods']) else None
647
+
648
+ if idmax_long_periods and idmin_long_periods and idmax_long_periods>0 and idmin_long_periods>0:
649
+ if idmax_long_periods>idmin_long_periods and idmax_long_periods < len(pd_candles):
650
+ # Falling from prev peak
651
+ last_peak = pd_candles.iloc[idmax_long_periods]
652
+ fib_target_long_periods = last_peak[f'fib_{target_fib_level}_long_periods'] if not math.isnan(last_peak[f'fib_{target_fib_level}_long_periods']) else None
653
+
654
+ else:
655
+ # Bouncing from prev bottom
656
+ if idmin_long_periods < len(pd_candles):
657
+ last_bottom = pd_candles.iloc[idmin_long_periods]
658
+ fib_target_long_periods = last_bottom[f'fib_{target_fib_level}_long_periods'] if not math.isnan(last_bottom[f'fib_{target_fib_level}_long_periods']) else None
659
+
660
+ return {
661
+ 'short_periods' : {
662
+ 'idmin' : idmin_short_periods,
663
+ 'idmax' : idmax_short_periods,
664
+ 'min' : min_short_periods,
665
+ 'max' : max_short_periods,
666
+ 'fib_target' : fib_target_short_periods,
667
+ },
668
+ 'long_periods' : {
669
+ 'idmin' : idmin_long_periods,
670
+ 'idmax' : idmax_long_periods,
671
+ 'min' : min_long_periods,
672
+ 'max' : max_long_periods,
673
+ 'fib_target' : fib_target_long_periods
674
+ }
675
+ }
676
+
609
677
  '''
610
678
  The implementation from Geeksforgeeks https://www.geeksforgeeks.org/find-indices-of-all-local-maxima-and-local-minima-in-an-array/ is wrong.
611
679
  If you have consecutive-duplicates, things will gall apart!
@@ -5,7 +5,7 @@ import pandas as pd
5
5
  import numpy as np
6
6
  from tabulate import tabulate
7
7
 
8
- from util.slack_notification_util import slack_dispatch_notification
8
+ from siglab_py.util.slack_notification_util import slack_dispatch_notification
9
9
 
10
10
  from siglab_py.constants import LogLevel
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siglab_py
3
- Version: 0.5.36
3
+ Version: 0.5.38
4
4
  Summary: Market data fetches, TA calculations and generic order gateway.
5
5
  Author: r0bbarh00d
6
6
  Author-email: r0bbarh00d <r0bbarh00d@gmail.com>