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

@@ -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
 
@@ -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
@@ -433,8 +434,11 @@ def compute_candles_stats(
433
434
 
434
435
  pd_candles['fvg_mitigated'] = pd_candles.apply(lambda row: compute_fvg_mitigated(row, pd_candles), axis=1)
435
436
 
436
-
437
- # 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
+ '''
438
442
  pd_candles.loc[:,'close_delta'] = pd_candles['close'].diff()
439
443
  pd_candles.loc[:,'close_delta_percent'] = pd_candles['close'].pct_change()
440
444
  lo_up = pd_candles['close_delta'].clip(lower=0)
@@ -608,6 +612,68 @@ def compute_candles_stats(
608
612
  'close_vs_ema_inflection'
609
613
  ] = np.sign(pd_candles['close'] - pd_candles['ema_long_periods'])
610
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
+
611
677
  '''
612
678
  The implementation from Geeksforgeeks https://www.geeksforgeeks.org/find-indices-of-all-local-maxima-and-local-minima-in-an-array/ is wrong.
613
679
  If you have consecutive-duplicates, things will gall apart!
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siglab_py
3
- Version: 0.5.37
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>
@@ -22,18 +22,18 @@ siglab_py/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  siglab_py/tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  siglab_py/tests/integration/market_data_util_tests.py,sha256=p-RWIJZLyj0lAdfi4QTIeAttCm_e8mEVWFKh4OWuogU,7189
24
24
  siglab_py/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- siglab_py/tests/unit/analytic_util_tests.py,sha256=9tAg7cLDEJ3ueYIQxMYMtPKtZQValKAbRfFgVY_L8dQ,4413
25
+ siglab_py/tests/unit/analytic_util_tests.py,sha256=Tffqy6ngMDj71NkwWvswRln8uhLUJ-RckhbTMN-jVX4,5474
26
26
  siglab_py/tests/unit/market_data_util_tests.py,sha256=A1y83itISmMJdn6wLpfwcr4tGola8wTf1D1xbelMvgw,2026
27
27
  siglab_py/tests/unit/trading_util_tests.py,sha256=9DZmTZlW55lPtNfTCukgDdiyBiMYv9R4mEFWJIJiTNg,3870
28
28
  siglab_py/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- siglab_py/util/analytic_util.py,sha256=lOQoObczb6Z4AZGevKOwuSTdNVKA2QhwAKa36LrMf7w,56524
29
+ siglab_py/util/analytic_util.py,sha256=vZ8G8Kpb2dYoeV5ruIaoVz4lUcVFAILsQVF-zuFb9yk,60287
30
30
  siglab_py/util/aws_util.py,sha256=KGmjHrr1rpnnxr33nXHNzTul4tvyyxl9p6gpwNv0Ygc,2557
31
31
  siglab_py/util/market_data_util.py,sha256=mUXg4uaiX3b6_klgJWIEgnUQU4IUd6CwTOqKLiQWRlU,31307
32
32
  siglab_py/util/notification_util.py,sha256=tNZMUkkjz4q1CKqcQq62oEmZgHgNIwz2Iw9J22V22Zw,2668
33
33
  siglab_py/util/retry_util.py,sha256=g-UU6pkPouWZZRZEqP99R2Z0lX5xzckYkzjwqqSDpVQ,922
34
34
  siglab_py/util/slack_notification_util.py,sha256=G27n-adbT3Q6oaHSMvu_Nom794rrda5PprSF-zvmzkM,1912
35
35
  siglab_py/util/trading_util.py,sha256=-TGNgJdy4HMDPgq31KQn_lRawFxuXnFU5NnLRb1XM5o,5757
36
- siglab_py-0.5.37.dist-info/METADATA,sha256=jaOC_0EKsjoghv2MUr397p7alkxIUGx5WS1OHxM7_IE,829
37
- siglab_py-0.5.37.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
38
- siglab_py-0.5.37.dist-info/top_level.txt,sha256=AbD4VR9OqmMOGlMJLkAVPGQMtUPIQv0t1BF5xmcLJSk,10
39
- siglab_py-0.5.37.dist-info/RECORD,,
36
+ siglab_py-0.5.38.dist-info/METADATA,sha256=GfE11A07HWATi24pVPfOLFZxxMPd1aKae-97cmeuOqo,829
37
+ siglab_py-0.5.38.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
38
+ siglab_py-0.5.38.dist-info/top_level.txt,sha256=AbD4VR9OqmMOGlMJLkAVPGQMtUPIQv0t1BF5xmcLJSk,10
39
+ siglab_py-0.5.38.dist-info/RECORD,,