siglab-py 0.5.12__tar.gz → 0.5.15__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.12 → siglab_py-0.5.15}/PKG-INFO +1 -1
- {siglab_py-0.5.12 → siglab_py-0.5.15}/pyproject.toml +1 -1
- {siglab_py-0.5.12 → siglab_py-0.5.15}/setup.cfg +1 -1
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/exchanges/futubull.py +1 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py +3 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/unit/analytic_util_tests.py +4 -2
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/unit/trading_util_tests.py +3 -3
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/analytic_util.py +20 -1
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py.egg-info/PKG-INFO +1 -1
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/constants.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/exchanges/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/exchanges/any_exchange.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/aggregated_orderbook_provider.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/candles_provider.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/candles_ta_provider.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/deribit_options_expiry_provider.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/orderbooks_provider.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/test_provider.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/tg_monitor.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/ordergateway/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/ordergateway/client.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/ordergateway/encrypt_keys_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/ordergateway/gateway.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/ordergateway/test_ordergateway.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/integration/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/integration/market_data_util_tests.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/unit/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/tests/unit/market_data_util_tests.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/__init__.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/aws_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/market_data_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/notification_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/retry_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/slack_notification_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/util/trading_util.py +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py.egg-info/SOURCES.txt +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py.egg-info/dependency_links.txt +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py.egg-info/requires.txt +0 -0
- {siglab_py-0.5.12 → siglab_py-0.5.15}/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.15"
|
|
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"}
|
|
@@ -30,6 +30,7 @@ API
|
|
|
30
30
|
stock basic info https://openapi.futunn.com/futu-api-doc/en/quote/get-static-info.html
|
|
31
31
|
historical candles https://openapi.futunn.com/futu-api-doc/en/quote/request-history-kline.html
|
|
32
32
|
realtime candles https://openapi.futunn.com/futu-api-doc/en/quote/get-kl.html
|
|
33
|
+
orderbook https://openapi.futunn.com/futu-api-doc/en/quote/get-order-book.html
|
|
33
34
|
real time quote https://openapi.futunn.com/futu-api-doc/en/quote/get-stock-quote.html
|
|
34
35
|
open orders https://openapi.futunn.com/futu-api-doc/en/trade/get-order-list.html
|
|
35
36
|
historical orders https://openapi.futunn.com/futu-api-doc/en/trade/get-history-order-list.html
|
{siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py
RENAMED
|
@@ -21,6 +21,9 @@ Usage:
|
|
|
21
21
|
|
|
22
22
|
python futu_candles_ta_to_csv.py --symbol AAPL --end_date "2025-03-11 0:0:0" --start_date "2024-03-11 0:0:0" --market US --trdmarket US --security_firm FUTUSECURITIES --security_type STOCK --compute_ta Y --pypy_compatible N
|
|
23
23
|
|
|
24
|
+
Gold contracts? Note, symbol is case sensitive with Futu.
|
|
25
|
+
python futu_candles_ta_to_csv.py --symbol US.GCmain --end_date "2025-03-11 0:0:0" --start_date "2021-03-11 0:0:0" --market US --trdmarket FUTURES --security_firm FUTUSECURITIES --security_type FUTURE --compute_ta Y --pypy_compatible N
|
|
26
|
+
|
|
24
27
|
(Remember: python -mpip install siglab_py)
|
|
25
28
|
|
|
26
29
|
This script is pypy compatible. Set "pypy_compatible" to True, in which case "compute_candles_stats" will skip calculation for TAs which requires: scipy, statsmodels, scikit-learn, sklearn.preprocessing
|
|
@@ -50,7 +50,7 @@ class AnalyticUtilTests(unittest.TestCase):
|
|
|
50
50
|
'is_green', 'pct_change_close',
|
|
51
51
|
'sma_short_periods', 'sma_long_periods', 'ema_short_periods', 'ema_long_periods', 'ema_close',
|
|
52
52
|
'std', 'std_percent',
|
|
53
|
-
'
|
|
53
|
+
'vwap_short_periods', 'vwap_long_periods',
|
|
54
54
|
'candle_height_percent', 'candle_height_percent_rounded',
|
|
55
55
|
'log_return', 'interval_hist_vol', 'annualized_hist_vol',
|
|
56
56
|
'chop_against_ema',
|
|
@@ -61,7 +61,9 @@ class AnalyticUtilTests(unittest.TestCase):
|
|
|
61
61
|
'boillenger_upper', 'boillenger_lower', 'boillenger_channel_height', 'boillenger_upper_agg', 'boillenger_lower_agg', 'boillenger_channel_height_agg',
|
|
62
62
|
'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',
|
|
63
63
|
'fvg_low', 'fvg_high', 'fvg_gap', 'fvg_mitigated',
|
|
64
|
-
'close_delta', 'close_delta_percent', 'up', 'down',
|
|
64
|
+
'close_delta', 'close_delta_percent', 'up', 'down',
|
|
65
|
+
'rsi', 'ema_rsi', 'rsi_max', 'rsi_idmax', 'rsi_min', 'rsi_idmin', 'rsi_trend',
|
|
66
|
+
'typical_price',
|
|
65
67
|
'money_flow', 'money_flow_positive', 'money_flow_negative', 'positive_flow_sum', 'negative_flow_sum', 'money_flow_ratio', 'mfi',
|
|
66
68
|
'macd', 'signal', 'macd_minus_signal',
|
|
67
69
|
'fib_618_short_periods', 'fib_618_long_periods',
|
|
@@ -13,7 +13,7 @@ Have a look at this for a visual explaination how "Gradually tightened stops" wo
|
|
|
13
13
|
|
|
14
14
|
# @unittest.skip("Skip all integration tests.")
|
|
15
15
|
class TradingUtilTests(unittest.TestCase):
|
|
16
|
-
def
|
|
16
|
+
def test_calc_eff_trailing_sl_case1(self):
|
|
17
17
|
tp_min_percent : float = 1.5
|
|
18
18
|
tp_max_percent : float = 2.5
|
|
19
19
|
sl_percent_trailing : float = 50 # Trailing stop loss in percent
|
|
@@ -30,7 +30,7 @@ class TradingUtilTests(unittest.TestCase):
|
|
|
30
30
|
)
|
|
31
31
|
assert(effective_tp_trailing_percent==50) # Generous trailing SL when trading starting out and pnl small.
|
|
32
32
|
|
|
33
|
-
def
|
|
33
|
+
def test_calc_eff_trailing_sl_case2(self):
|
|
34
34
|
tp_min_percent : float = 1.5
|
|
35
35
|
tp_max_percent : float = 2.5
|
|
36
36
|
sl_percent_trailing : float = 50 # Trailing stop loss in percent
|
|
@@ -47,7 +47,7 @@ class TradingUtilTests(unittest.TestCase):
|
|
|
47
47
|
)
|
|
48
48
|
assert(effective_tp_trailing_percent==25) # Intermediate trailing SL
|
|
49
49
|
|
|
50
|
-
def
|
|
50
|
+
def test_calc_eff_trailing_sl_case3(self):
|
|
51
51
|
tp_min_percent : float = 1.5
|
|
52
52
|
tp_max_percent : float = 2.5
|
|
53
53
|
sl_percent_trailing : float = 50 # Trailing stop loss in percent
|
|
@@ -118,9 +118,11 @@ def compute_candles_stats(
|
|
|
118
118
|
pd_candles['ema_long_periods'] = close_long_periods_ewm.mean()
|
|
119
119
|
pd_candles['ema_close'] = pd_candles['ema_long_periods'] # Alias, shorter name
|
|
120
120
|
pd_candles['std'] = close_long_periods_rolling.std()
|
|
121
|
-
|
|
122
121
|
pd_candles['std_percent'] = pd_candles['std'] / pd_candles['ema_close'] * 100
|
|
123
122
|
|
|
123
|
+
pd_candles['vwap_short_periods'] = (pd_candles['close'] * pd_candles['volume']).rolling(window=int(sliding_window_how_many_candles/slow_fast_interval_ratio)).sum() / pd_candles['volume'].rolling(window=int(sliding_window_how_many_candles/slow_fast_interval_ratio)).sum()
|
|
124
|
+
pd_candles['vwap_long_periods'] = (pd_candles['close'] * pd_candles['volume']).rolling(window=sliding_window_how_many_candles).sum() / pd_candles['volume'].rolling(window=sliding_window_how_many_candles).sum()
|
|
125
|
+
|
|
124
126
|
pd_candles['candle_height_percent'] = pd_candles['candle_height'] / pd_candles['ema_close'] * 100
|
|
125
127
|
pd_candles['candle_height_percent_rounded'] = pd_candles['candle_height_percent'].round().astype('Int64')
|
|
126
128
|
|
|
@@ -360,6 +362,23 @@ def compute_candles_stats(
|
|
|
360
362
|
span=rsi_sliding_window_how_many_candles if rsi_sliding_window_how_many_candles else sliding_window_how_many_candles,
|
|
361
363
|
adjust=False).mean()
|
|
362
364
|
|
|
365
|
+
rsi_rolling = pd_candles['rsi'].rolling(window=int(rsi_sliding_window_how_many_candles if rsi_sliding_window_how_many_candles else sliding_window_how_many_candles))
|
|
366
|
+
pd_candles['rsi_max'] = rsi_rolling.max()
|
|
367
|
+
pd_candles['rsi_idmax'] = rsi_rolling.apply(lambda x : x.idxmax())
|
|
368
|
+
pd_candles['rsi_min'] = rsi_rolling.min()
|
|
369
|
+
pd_candles['rsi_idmin'] = rsi_rolling.apply(lambda x : x.idxmin())
|
|
370
|
+
|
|
371
|
+
def rsi_trend(
|
|
372
|
+
row,
|
|
373
|
+
rsi_upper_threshold : float = 70,
|
|
374
|
+
rsi_lower_threshold : float = 30):
|
|
375
|
+
if row['rsi_idmax'] > row['rsi_idmin']:
|
|
376
|
+
return 'DOWN' if row.name > row['rsi_idmax'] and row['rsi'] <= rsi_upper_threshold else 'up'
|
|
377
|
+
else:
|
|
378
|
+
return 'UP' if row.name > row['rsi_idmin'] and row['rsi'] >= rsi_lower_threshold else 'down'
|
|
379
|
+
|
|
380
|
+
pd_candles['rsi_trend'] = pd_candles.apply(lambda row: rsi_trend(row), axis=1)
|
|
381
|
+
|
|
363
382
|
|
|
364
383
|
# MFI (Money Flow Index) https://randerson112358.medium.com/algorithmic-trading-strategy-using-money-flow-index-mfi-python-aa46461a5ea5
|
|
365
384
|
pd_candles['typical_price'] = (pd_candles['high'] + pd_candles['low'] + pd_candles['close']) / 3
|
|
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.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/candles_ta_provider.py
RENAMED
|
File without changes
|
{siglab_py-0.5.12 → siglab_py-0.5.15}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py
RENAMED
|
File without changes
|
|
File without changes
|
{siglab_py-0.5.12 → siglab_py-0.5.15}/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
|