siglab-py 0.5.37__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.
- {siglab_py-0.5.37 → siglab_py-0.5.38}/PKG-INFO +1 -1
- {siglab_py-0.5.37 → siglab_py-0.5.38}/pyproject.toml +1 -1
- {siglab_py-0.5.37 → siglab_py-0.5.38}/setup.cfg +1 -1
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/unit/analytic_util_tests.py +27 -2
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/analytic_util.py +76 -10
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py.egg-info/PKG-INFO +1 -1
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/constants.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/exchanges/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/exchanges/any_exchange.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/exchanges/futubull.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/aggregated_orderbook_provider.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/candles_provider.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/candles_ta_provider.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/deribit_options_expiry_provider.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/orderbooks_provider.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/test_provider.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/tg_monitor.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/ordergateway/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/ordergateway/client.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/ordergateway/encrypt_keys_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/ordergateway/gateway.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/ordergateway/test_ordergateway.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/integration/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/integration/market_data_util_tests.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/unit/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/unit/market_data_util_tests.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/tests/unit/trading_util_tests.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/__init__.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/aws_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/market_data_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/notification_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/retry_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/slack_notification_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/util/trading_util.py +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py.egg-info/SOURCES.txt +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py.egg-info/dependency_links.txt +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py.egg-info/requires.txt +0 -0
- {siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "siglab_py"
|
|
7
|
-
version = "0.5.
|
|
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"}
|
|
@@ -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.
|
|
87
|
-
c.
|
|
88
|
-
d.
|
|
89
|
-
e.
|
|
90
|
-
f.
|
|
91
|
-
g.
|
|
92
|
-
h.
|
|
93
|
-
i.
|
|
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
|
-
|
|
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!
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/candles_ta_provider.py
RENAMED
|
File without changes
|
{siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py
RENAMED
|
File without changes
|
|
File without changes
|
{siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py
RENAMED
|
File without changes
|
{siglab_py-0.5.37 → siglab_py-0.5.38}/siglab_py/market_data_providers/orderbooks_provider.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
|
|
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
|