siglab-py 0.1.21__tar.gz → 0.1.22__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 (37) hide show
  1. {siglab_py-0.1.21 → siglab_py-0.1.22}/PKG-INFO +1 -1
  2. {siglab_py-0.1.21 → siglab_py-0.1.22}/pyproject.toml +1 -1
  3. {siglab_py-0.1.21 → siglab_py-0.1.22}/setup.cfg +1 -1
  4. siglab_py-0.1.22/siglab_py/market_data_providers/futu_candles.py +187 -0
  5. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/util/market_data_util.py +1 -1
  6. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py.egg-info/PKG-INFO +1 -1
  7. siglab_py-0.1.21/siglab_py/market_data_providers/futu_candles.py +0 -95
  8. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/__init__.py +0 -0
  9. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/constants.py +0 -0
  10. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/exchanges/__init__.py +0 -0
  11. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/exchanges/any_exchange.py +0 -0
  12. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/exchanges/futubull.py +0 -0
  13. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/__init__.py +0 -0
  14. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/aggregated_orderbook_provider.py +0 -0
  15. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/candles_provider.py +0 -0
  16. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/candles_ta_provider.py +0 -0
  17. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/deribit_options_expiry_provider.py +0 -0
  18. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/orderbooks_provider.py +0 -0
  19. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/market_data_providers/test_provider.py +0 -0
  20. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/ordergateway/__init__.py +0 -0
  21. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/ordergateway/client.py +0 -0
  22. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/ordergateway/encrypt_keys_util.py +0 -0
  23. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/ordergateway/gateway.py +0 -0
  24. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/ordergateway/test_ordergateway.py +0 -0
  25. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/tests/__init__.py +0 -0
  26. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/tests/integration/__init__.py +0 -0
  27. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/tests/integration/market_data_util_tests.py +0 -0
  28. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/tests/unit/__init__.py +0 -0
  29. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/tests/unit/analytic_util_tests.py +0 -0
  30. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/util/__init__.py +0 -0
  31. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/util/analytic_util.py +0 -0
  32. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/util/aws_util.py +0 -0
  33. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py/util/retry_util.py +0 -0
  34. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py.egg-info/SOURCES.txt +0 -0
  35. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py.egg-info/dependency_links.txt +0 -0
  36. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py.egg-info/requires.txt +0 -0
  37. {siglab_py-0.1.21 → siglab_py-0.1.22}/siglab_py.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siglab_py
3
- Version: 0.1.21
3
+ Version: 0.1.22
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.1.21"
7
+ version = "0.1.22"
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.1.21
3
+ version = 0.1.22
4
4
  description = Market data fetches, TA calculations and generic order gateway.
5
5
  author = r0bbarh00d
6
6
  author_email = r0bbarh00d@gmail.com
@@ -0,0 +1,187 @@
1
+ import sys
2
+ import logging
3
+ import argparse
4
+ from datetime import datetime
5
+ from typing import Dict, Union
6
+ from enum import Enum
7
+ import asyncio
8
+
9
+ from futu import *
10
+
11
+ from siglab_py.exchanges.futubull import Futubull
12
+ from siglab_py.util.market_data_util import fetch_candles
13
+ from siglab_py.util.analytic_util import compute_candles_stats
14
+
15
+ '''
16
+ Usage:
17
+ python futu_candles.py --symbol HK.00700 --end_date 2025-03-11 --start_date 2024-03-11 --market HK --trdmarket HK --security_firm FUTUSECURITIES --security_type STOCK --compute_ta Y
18
+
19
+ This script is NOT pypy compatible.
20
+
21
+ If debugging from VSCode, launch.json:
22
+
23
+ {
24
+ "version": "0.2.0",
25
+ "configurations": [
26
+ {
27
+ "name": "Python Debugger: Current File",
28
+ "type": "debugpy",
29
+ "request": "launch",
30
+ "program": "${file}",
31
+ "console": "integratedTerminal",
32
+ "args" : [
33
+ "--symbol", "HK.00700",
34
+ "--end_date", "2025-03-11 0:0:0",
35
+ "--start_date", "2024-03-11 0:0:0",
36
+ "--market", "HK",
37
+ "--trdmarket", "HK",
38
+ "--security_firm", "FUTUSECURITIES",
39
+ "--security_type", "STOCK",
40
+ "--compute_ta", "Y"
41
+ ],
42
+ "env": {
43
+ "PYTHONPATH": "${workspaceFolder}"
44
+ }
45
+ }
46
+ ]
47
+ }
48
+ '''
49
+ end_date : datetime = datetime.today()
50
+ end_date = datetime(end_date.year, end_date.month, end_date.day)
51
+ start_date : datetime = end_date - timedelta(days=365)
52
+
53
+ param : Dict = {
54
+ 'symbol' : None,
55
+ 'start_date' : start_date,
56
+ 'end_date' : end_date,
57
+ 'trdmarket' : TrdMarket.HK,
58
+ 'security_firm' : SecurityFirm.FUTUSECURITIES,
59
+ 'market' : Market.HK,
60
+ 'security_type' : SecurityType.STOCK,
61
+ 'daemon' : {
62
+ 'host' : '127.0.0.1',
63
+ 'port' : 11111
64
+ },
65
+ 'output_filename' : 'candles_$SYMBOL$.csv'
66
+ }
67
+
68
+ class LogLevel(Enum):
69
+ CRITICAL = 50
70
+ ERROR = 40
71
+ WARNING = 30
72
+ INFO = 20
73
+ DEBUG = 10
74
+ NOTSET = 0
75
+
76
+ logging.Formatter.converter = time.gmtime
77
+ logger = logging.getLogger()
78
+ log_level = logging.INFO # DEBUG --> INFO --> WARNING --> ERROR
79
+ logger.setLevel(log_level)
80
+ format_str = '%(asctime)s %(message)s'
81
+ formatter = logging.Formatter(format_str)
82
+ sh = logging.StreamHandler()
83
+ sh.setLevel(log_level)
84
+ sh.setFormatter(formatter)
85
+ logger.addHandler(sh)
86
+
87
+ def log(message : str, log_level : LogLevel = LogLevel.INFO):
88
+ if log_level.value<LogLevel.WARNING.value:
89
+ logger.info(f"{datetime.now()} {message}")
90
+
91
+ elif log_level.value==LogLevel.WARNING.value:
92
+ logger.warning(f"{datetime.now()} {message}")
93
+
94
+ elif log_level.value==LogLevel.ERROR.value:
95
+ logger.error(f"{datetime.now()} {message}")
96
+
97
+ def parse_args():
98
+ parser = argparse.ArgumentParser() # type: ignore
99
+ parser.add_argument("--symbol", help="symbol, example HK.00700", default=None)
100
+ parser.add_argument("--start_date", help="Format: %Y-%m-%d %H:%M:%S", default=None)
101
+ parser.add_argument("--end_date", help="Format: %Y-%m-%d %H:%M:%S", default=None)
102
+
103
+ '''
104
+ Enums here:
105
+ https://openapi.futunn.com/futu-api-doc/en/quote/quote.html#66
106
+ https://openapi.futunn.com/futu-api-doc/en/trade/trade.html#9434
107
+ '''
108
+ parser.add_argument("--market", help="market: HK SH SZ US AU CA FX", default=Market.HK)
109
+ parser.add_argument("--trdmarket", help="trdmarket: HK, HKCC, HKFUND, FUTURES, CN, CA, AU, JP, MY, SG, US, USFUND", default=TrdMarket.HK)
110
+ parser.add_argument("--security_firm", help="security_firm: FUTUSECURITIES (HK), FUTUINC (US), FUTUSG (SG), FUTUAU (AU)", default=SecurityFirm.FUTUSECURITIES)
111
+ parser.add_argument("--security_type", help="STOCK, BOND, ETF, FUTURE, WARRANT, IDX ... ", default=SecurityType.STOCK)
112
+
113
+ parser.add_argument("--compute_ta", help="Compute technical indicators?. Y or N (default).", default='N')
114
+ parser.add_argument("--candle_size", help="candle interval: 1m, 1h, 1d... etc", default='1h')
115
+ parser.add_argument("--ma_long_intervals", help="Window size in number of intervals for higher timeframe", default=24)
116
+ parser.add_argument("--ma_short_intervals", help="Window size in number of intervals for lower timeframe", default=8)
117
+ parser.add_argument("--boillenger_std_multiples", help="Boillenger bands: # std", default=2)
118
+
119
+ args = parser.parse_args()
120
+ param['symbol'] = args.symbol.strip().upper()
121
+
122
+ param['start_date'] = datetime.strptime(args.start_date, "%Y-%m-%d %H:%M:%S") if args.start_date else start_date
123
+ param['end_date'] = datetime.strptime(args.end_date, "%Y-%m-%d %H:%M:%S") if args.end_date else end_date
124
+
125
+ param['market'] = args.market
126
+ param['trdmarket'] = args.trdmarket
127
+ param['security_firm'] = args.security_firm
128
+
129
+ param['output_filename'] = param['output_filename'].replace('$SYMBOL$', param['symbol'])
130
+
131
+ if args.compute_ta:
132
+ if args.compute_ta=='Y':
133
+ param['compute_ta'] = True
134
+ else:
135
+ param['compute_ta'] = False
136
+ else:
137
+ param['compute_ta'] = False
138
+ param['candle_size'] = args.candle_size
139
+ param['ma_long_intervals'] = int(args.ma_long_intervals)
140
+ param['ma_short_intervals'] = int(args.ma_short_intervals)
141
+ param['boillenger_std_multiples'] = int(args.boillenger_std_multiples)
142
+
143
+ async def main():
144
+ parse_args()
145
+
146
+ fh = logging.FileHandler(f"futu_candles.log")
147
+ fh.setLevel(log_level)
148
+ fh.setFormatter(formatter)
149
+ logger.addHandler(fh) # type: ignore
150
+
151
+ exchange = Futubull(param)
152
+
153
+ pd_candles: Union[pd.DataFrame, None] = fetch_candles(
154
+ start_ts=int(start_date.timestamp()),
155
+ end_ts=int(end_date.timestamp()),
156
+ exchange=exchange,
157
+ normalized_symbols=[ param['symbol'] ],
158
+ candle_size='1d'
159
+ )[param['symbol']]
160
+
161
+ assert pd_candles is not None
162
+
163
+ if pd_candles is not None:
164
+ assert len(pd_candles) > 0, "No candles returned."
165
+ expected_columns = {'exchange', 'symbol', 'timestamp_ms', 'open', 'high', 'low', 'close', 'volume', 'datetime_utc', 'datetime', 'year', 'month', 'day', 'hour', 'minute'}
166
+ assert set(pd_candles.columns) >= expected_columns, "Missing expected columns."
167
+ assert pd_candles['timestamp_ms'].notna().all(), "timestamp_ms column contains NaN values."
168
+ assert pd_candles['timestamp_ms'].is_monotonic_increasing, "Timestamps are not in ascending order."
169
+
170
+ if param['compute_ta']:
171
+ start = time.time()
172
+ compute_candles_stats(
173
+ pd_candles=pd_candles,
174
+ boillenger_std_multiples=param['boillenger_std_multiples'],
175
+ sliding_window_how_many_candles=param['ma_long_intervals'],
176
+ slow_fast_interval_ratio=(param['ma_long_intervals']/param['ma_short_intervals']),
177
+ pypy_compat=False
178
+ )
179
+ compute_candles_stats_elapsed_ms = int((time.time() - start) *1000)
180
+ log(f"TA calculated, took {compute_candles_stats_elapsed_ms} ms")
181
+
182
+ log(f"Candles (# rows: {pd_candles.shape[0]}) written to {param['output_filename']}")
183
+ pd_candles.to_csv(param['output_filename'])
184
+
185
+ sys.exit()
186
+
187
+ asyncio.run(main())
@@ -15,7 +15,7 @@ from yahoofinancials import YahooFinancials
15
15
  # yfinance allows intervals '1m', '5m', '15m', '1h', '1d', '1wk', '1mo'. yahoofinancials not as flexible
16
16
  import yfinance as yf
17
17
 
18
- from exchanges.futubull import Futubull
18
+ from siglab_py.exchanges.futubull import Futubull
19
19
 
20
20
  def timestamp_to_datetime_cols(pd_candles : pd.DataFrame):
21
21
  pd_candles['datetime'] = pd_candles['timestamp_ms'].apply(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siglab-py
3
- Version: 0.1.21
3
+ Version: 0.1.22
4
4
  Summary: Market data fetches, TA calculations and generic order gateway.
5
5
  Author: r0bbarh00d
6
6
  Author-email: r0bbarh00d <r0bbarh00d@gmail.com>
@@ -1,95 +0,0 @@
1
- import argparse
2
- from datetime import datetime
3
- from typing import Dict, Union
4
- import asyncio
5
-
6
- from futu import *
7
-
8
- from siglab_py.exchanges.futubull import Futubull
9
- from siglab_py.util.market_data_util import fetch_candles
10
- from siglab_py.util.analytic_util import compute_candles_stats
11
-
12
- end_date : datetime = datetime.today()
13
- start_date : datetime = end_date - timedelta(days=365)
14
-
15
- param : Dict = {
16
- 'symbol' : None,
17
- 'trdmarket' : TrdMarket.HK,
18
- 'security_firm' : SecurityFirm.FUTUSECURITIES,
19
- 'market' : Market.HK,
20
- 'security_type' : SecurityType.STOCK,
21
- 'daemon' : {
22
- 'host' : '127.0.0.1',
23
- 'port' : 11111
24
- }
25
- }
26
-
27
- '''
28
- If debugging from VSCode, launch.json:
29
-
30
- {
31
- "version": "0.2.0",
32
- "configurations": [
33
- {
34
- "name": "Python Debugger: Current File",
35
- "type": "debugpy",
36
- "request": "launch",
37
- "program": "${file}",
38
- "console": "integratedTerminal",
39
- "args" : [
40
- "--symbol", "HK.00700",
41
- "--market", "HK",
42
- "--trdmarket", "HK",
43
- "--security_firm", "FUTUSECURITIES",
44
- "--security_type", "STOCK"
45
- ],
46
- "env": {
47
- "PYTHONPATH": "${workspaceFolder}"
48
- }
49
- }
50
- ]
51
- }
52
- '''
53
- def parse_args():
54
- parser = argparse.ArgumentParser() # type: ignore
55
- parser.add_argument("--symbol", help="symbol, example HK.00700", default=None)
56
-
57
- '''
58
- Enums here:
59
- https://openapi.futunn.com/futu-api-doc/en/quote/quote.html#66
60
- https://openapi.futunn.com/futu-api-doc/en/trade/trade.html#9434
61
- '''
62
- parser.add_argument("--market", help="market: HK SH SZ US AU CA FX", default=Market.HK)
63
- parser.add_argument("--trdmarket", help="trdmarket: HK, HKCC, HKFUND, FUTURES, CN, CA, AU, JP, MY, SG, US, USFUND", default=TrdMarket.HK)
64
- parser.add_argument("--security_firm", help="security_firm: FUTUSECURITIES (HK), FUTUINC (US), FUTUSG (SG), FUTUAU (AU)", default=SecurityFirm.FUTUSECURITIES)
65
- parser.add_argument("--security_type", help="STOCK, BOND, ETF, FUTURE, WARRANT, IDX ... ", default=SecurityType.STOCK)
66
-
67
- args = parser.parse_args()
68
- param['symbol'] = args.symbol
69
- param['market'] = args.market
70
- param['trdmarket'] = args.trdmarket
71
- param['security_firm'] = args.security_firm
72
-
73
- async def main():
74
- parse_args()
75
-
76
- exchange = Futubull(param)
77
-
78
- pd_candles: Union[pd.DataFrame, None] = fetch_candles(
79
- start_ts=int(start_date.timestamp()),
80
- end_ts=int(end_date.timestamp()),
81
- exchange=exchange,
82
- normalized_symbols=[ param['symbol'] ],
83
- candle_size='1d'
84
- )[param['symbol']]
85
-
86
- assert pd_candles is not None
87
-
88
- if pd_candles is not None:
89
- assert len(pd_candles) > 0, "No candles returned."
90
- expected_columns = {'exchange', 'symbol', 'timestamp_ms', 'open', 'high', 'low', 'close', 'volume', 'datetime_utc', 'datetime', 'year', 'month', 'day', 'hour', 'minute'}
91
- assert set(pd_candles.columns) >= expected_columns, "Missing expected columns."
92
- assert pd_candles['timestamp_ms'].notna().all(), "timestamp_ms column contains NaN values."
93
- assert pd_candles['timestamp_ms'].is_monotonic_increasing, "Timestamps are not in ascending order."
94
-
95
- asyncio.run(main())