siglab-py 0.3.9__tar.gz → 0.3.11__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.3.9 → siglab_py-0.3.11}/PKG-INFO +1 -1
- {siglab_py-0.3.9 → siglab_py-0.3.11}/pyproject.toml +1 -1
- {siglab_py-0.3.9 → siglab_py-0.3.11}/setup.cfg +1 -1
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/ordergateway/gateway.py +2 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/market_data_util.py +47 -44
- siglab_py-0.3.11/siglab_py/util/retry_util.py +23 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py.egg-info/PKG-INFO +1 -1
- siglab_py-0.3.9/siglab_py/util/retry_util.py +0 -15
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/constants.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/exchanges/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/exchanges/any_exchange.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/exchanges/futubull.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/aggregated_orderbook_provider.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/candles_provider.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/candles_ta_provider.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/deribit_options_expiry_provider.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/orderbooks_provider.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/test_provider.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/ordergateway/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/ordergateway/client.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/ordergateway/encrypt_keys_util.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/ordergateway/test_ordergateway.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/integration/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/integration/market_data_util_tests.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/unit/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/unit/analytic_util_tests.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/unit/market_data_util_tests.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/tests/unit/trading_util_tests.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/__init__.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/analytic_util.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/aws_util.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/notification_util.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/slack_notification_util.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/util/trading_util.py +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py.egg-info/SOURCES.txt +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py.egg-info/dependency_links.txt +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py.egg-info/requires.txt +0 -0
- {siglab_py-0.3.9 → siglab_py-0.3.11}/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.3.
|
|
7
|
+
version = "0.3.11"
|
|
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"}
|
|
@@ -452,6 +452,8 @@ async def execute_one_position(
|
|
|
452
452
|
'reduceOnly': slice.reduce_only
|
|
453
453
|
}
|
|
454
454
|
if position.order_type=='limit':
|
|
455
|
+
order_params['postOnly'] = True
|
|
456
|
+
|
|
455
457
|
if not param['dry_run']:
|
|
456
458
|
executed_order = await exchange.create_order( # type: ignore
|
|
457
459
|
symbol = position.ticker,
|
|
@@ -19,6 +19,7 @@ from yahoofinancials import YahooFinancials
|
|
|
19
19
|
# yfinance allows intervals '1m', '5m', '15m', '1h', '1d', '1wk', '1mo'. yahoofinancials not as flexible
|
|
20
20
|
import yfinance as yf
|
|
21
21
|
|
|
22
|
+
from siglab_py.util.retry_util import retry
|
|
22
23
|
from siglab_py.exchanges.futubull import Futubull
|
|
23
24
|
from siglab_py.exchanges.any_exchange import AnyExchange
|
|
24
25
|
|
|
@@ -516,55 +517,57 @@ def _fetch_candles_ccxt(
|
|
|
516
517
|
candle_size : str,
|
|
517
518
|
num_candles_limit : int = 100
|
|
518
519
|
) -> Dict[str, Union[pd.DataFrame, None]]:
|
|
519
|
-
|
|
520
|
+
rsp = {}
|
|
520
521
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
candles.
|
|
522
|
+
for ticker in normalized_symbols:
|
|
523
|
+
@retry(num_attempts=3, pause_between_retries_ms=1000)
|
|
524
|
+
def _fetch_ohlcv(exchange, symbol, timeframe, since, limit, params) -> Union[List, NoReturn]:
|
|
525
|
+
one_timeframe = f"1{timeframe[-1]}"
|
|
526
|
+
candles = exchange.fetch_ohlcv(symbol=symbol, timeframe=one_timeframe, since=since, limit=limit, params=params)
|
|
527
|
+
if candles and len(candles)>0:
|
|
528
|
+
candles.sort(key=lambda x : x[0], reverse=False)
|
|
526
529
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
def _calc_increment(candle_size):
|
|
530
|
-
increment = 1
|
|
531
|
-
num_intervals = int(candle_size[0])
|
|
532
|
-
interval_type = candle_size[-1]
|
|
533
|
-
if interval_type == "m":
|
|
534
|
-
increment = 60
|
|
535
|
-
elif interval_type == "h":
|
|
536
|
-
increment = 60*60
|
|
537
|
-
elif interval_type == "d":
|
|
538
|
-
increment = 60*60*24
|
|
539
|
-
else:
|
|
540
|
-
raise ValueError(f"Invalid candle_size {candle_size}")
|
|
541
|
-
return num_intervals * increment
|
|
542
|
-
|
|
543
|
-
all_candles = []
|
|
544
|
-
params = {}
|
|
545
|
-
this_cutoff = start_ts
|
|
546
|
-
while this_cutoff<end_ts:
|
|
547
|
-
candles = _fetch_ohlcv(exchange=exchange, symbol=ticker, timeframe=candle_size, since=int(this_cutoff * 1000), limit=num_candles_limit, params=params)
|
|
548
|
-
if candles and len(candles)>0:
|
|
549
|
-
all_candles = all_candles + [[ int(x[0]), float(x[1]), float(x[2]), float(x[3]), float(x[4]), float(x[5]) ] for x in candles if x[1] and x[2] and x[3] and x[4] and x[5] ]
|
|
550
|
-
|
|
551
|
-
record_ts = max([int(record[0]) for record in candles])
|
|
552
|
-
record_ts_str : str = str(record_ts)
|
|
553
|
-
if len(record_ts_str)==13:
|
|
554
|
-
record_ts = int(int(record_ts_str)/1000) # Convert from milli-seconds to seconds
|
|
530
|
+
return candles
|
|
555
531
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
532
|
+
def _calc_increment(candle_size):
|
|
533
|
+
increment = 1
|
|
534
|
+
num_intervals = int(candle_size[0])
|
|
535
|
+
interval_type = candle_size[-1]
|
|
536
|
+
if interval_type == "m":
|
|
537
|
+
increment = 60
|
|
538
|
+
elif interval_type == "h":
|
|
539
|
+
increment = 60*60
|
|
540
|
+
elif interval_type == "d":
|
|
541
|
+
increment = 60*60*24
|
|
542
|
+
else:
|
|
543
|
+
raise ValueError(f"Invalid candle_size {candle_size}")
|
|
544
|
+
return num_intervals * increment
|
|
545
|
+
|
|
546
|
+
all_candles = []
|
|
547
|
+
params = {}
|
|
548
|
+
this_cutoff = start_ts
|
|
549
|
+
while this_cutoff<end_ts:
|
|
550
|
+
candles = _fetch_ohlcv(exchange=exchange, symbol=ticker, timeframe=candle_size, since=int(this_cutoff * 1000), limit=num_candles_limit, params=params)
|
|
551
|
+
if candles and len(candles)>0:
|
|
552
|
+
all_candles = all_candles + [[ int(x[0]), float(x[1]), float(x[2]), float(x[3]), float(x[4]), float(x[5]) ] for x in candles if x[1] and x[2] and x[3] and x[4] and x[5] ]
|
|
553
|
+
|
|
554
|
+
record_ts = max([int(record[0]) for record in candles])
|
|
555
|
+
record_ts_str : str = str(record_ts)
|
|
556
|
+
if len(record_ts_str)==13:
|
|
557
|
+
record_ts = int(int(record_ts_str)/1000) # Convert from milli-seconds to seconds
|
|
558
|
+
|
|
559
|
+
this_cutoff = record_ts + _calc_increment(candle_size)
|
|
560
|
+
else:
|
|
561
|
+
this_cutoff += _calc_increment(candle_size)
|
|
559
562
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
563
|
+
columns = ['exchange', 'symbol', 'timestamp_ms', 'open', 'high', 'low', 'close', 'volume']
|
|
564
|
+
pd_all_candles = pd.DataFrame([ [ exchange.name, ticker, x[0], x[1], x[2], x[3], x[4], x[5] ] for x in all_candles], columns=columns)
|
|
565
|
+
fix_column_types(pd_all_candles)
|
|
566
|
+
pd_all_candles['pct_chg_on_close'] = pd_all_candles['close'].pct_change()
|
|
564
567
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
+
rsp[ticker] = pd_all_candles
|
|
569
|
+
|
|
570
|
+
return rsp
|
|
568
571
|
|
|
569
572
|
def fetch_deribit_btc_option_expiries(
|
|
570
573
|
market: str = 'BTC'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
def retry(
|
|
4
|
+
num_attempts : int = 1,
|
|
5
|
+
pause_between_retries_ms : int = 1000
|
|
6
|
+
):
|
|
7
|
+
def decorator(method):
|
|
8
|
+
def wrapper(*args, **kw):
|
|
9
|
+
for i in range(num_attempts):
|
|
10
|
+
try:
|
|
11
|
+
result = method(*args, **kw)
|
|
12
|
+
if i>0:
|
|
13
|
+
print(f"retry_util.retry done {method.__name__} on #{i+1} call. {args} {kw}")
|
|
14
|
+
return result
|
|
15
|
+
except Exception as retry_error:
|
|
16
|
+
if i==(num_attempts-1):
|
|
17
|
+
err_msg = f"retry_util.retry gave up {method.__name__} after {num_attempts} calls. {args} {kw}. {retry_error}"
|
|
18
|
+
raise Exception(err_msg) from retry_error
|
|
19
|
+
finally:
|
|
20
|
+
time.sleep(int(pause_between_retries_ms/1000))
|
|
21
|
+
|
|
22
|
+
return wrapper
|
|
23
|
+
return decorator
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
def retry(num_attempts : int = 1):
|
|
2
|
-
def decorator(method):
|
|
3
|
-
def wrapper(*args, **kw):
|
|
4
|
-
for i in range(num_attempts):
|
|
5
|
-
try:
|
|
6
|
-
result = method(*args, **kw)
|
|
7
|
-
if i>0:
|
|
8
|
-
print(f"retry_gizmo.retry succeeded: {method.__name__} on #{i+1} invocation. {args} {kw}")
|
|
9
|
-
return result
|
|
10
|
-
except Exception as retry_error:
|
|
11
|
-
if i==(num_attempts-1):
|
|
12
|
-
err_msg = f"retry_gizmo.retry failed: {method.__name__} after {num_attempts} invocations. {args} {kw}. {retry_error}"
|
|
13
|
-
raise Exception(err_msg) from retry_error
|
|
14
|
-
return wrapper
|
|
15
|
-
return decorator
|
|
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
|
{siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py
RENAMED
|
File without changes
|
|
File without changes
|
{siglab_py-0.3.9 → siglab_py-0.3.11}/siglab_py/market_data_providers/futu_candles_ta_to_csv.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
|