siglab-py 0.5.48__tar.gz → 0.5.51__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 (47) hide show
  1. {siglab_py-0.5.48 → siglab_py-0.5.51}/PKG-INFO +1 -1
  2. {siglab_py-0.5.48 → siglab_py-0.5.51}/pyproject.toml +1 -1
  3. {siglab_py-0.5.48 → siglab_py-0.5.51}/setup.cfg +1 -1
  4. siglab_py-0.5.51/siglab_py/tests/unit/simple_math_tests.py +235 -0
  5. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/unit/trading_util_tests.py +0 -21
  6. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/analytic_util.py +10 -0
  7. siglab_py-0.5.51/siglab_py/util/simple_math.py +205 -0
  8. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/trading_util.py +0 -12
  9. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py.egg-info/PKG-INFO +1 -1
  10. siglab_py-0.5.48/siglab_py/tests/unit/simple_math_tests.py +0 -87
  11. siglab_py-0.5.48/siglab_py/util/simple_math.py +0 -30
  12. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/__init__.py +0 -0
  13. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/constants.py +0 -0
  14. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/exchanges/__init__.py +0 -0
  15. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/exchanges/any_exchange.py +0 -0
  16. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/exchanges/futubull.py +0 -0
  17. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/__init__.py +0 -0
  18. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/aggregated_orderbook_provider.py +0 -0
  19. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/candles_provider.py +0 -0
  20. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/candles_ta_provider.py +0 -0
  21. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/ccxt_candles_ta_to_csv.py +0 -0
  22. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/deribit_options_expiry_provider.py +0 -0
  23. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/futu_candles_ta_to_csv.py +0 -0
  24. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/orderbooks_provider.py +0 -0
  25. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/test_provider.py +0 -0
  26. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/market_data_providers/tg_monitor.py +0 -0
  27. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/ordergateway/__init__.py +0 -0
  28. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/ordergateway/client.py +0 -0
  29. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/ordergateway/encrypt_keys_util.py +0 -0
  30. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/ordergateway/gateway.py +0 -0
  31. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/ordergateway/test_ordergateway.py +0 -0
  32. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/__init__.py +0 -0
  33. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/integration/__init__.py +0 -0
  34. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/integration/market_data_util_tests.py +0 -0
  35. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/unit/__init__.py +0 -0
  36. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/unit/analytic_util_tests.py +0 -0
  37. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/tests/unit/market_data_util_tests.py +0 -0
  38. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/__init__.py +0 -0
  39. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/aws_util.py +0 -0
  40. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/market_data_util.py +0 -0
  41. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/notification_util.py +0 -0
  42. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/retry_util.py +0 -0
  43. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py/util/slack_notification_util.py +0 -0
  44. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py.egg-info/SOURCES.txt +0 -0
  45. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py.egg-info/dependency_links.txt +0 -0
  46. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py.egg-info/requires.txt +0 -0
  47. {siglab_py-0.5.48 → siglab_py-0.5.51}/siglab_py.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siglab_py
3
- Version: 0.5.48
3
+ Version: 0.5.51
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.5.48"
7
+ version = "0.5.51"
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.5.48
3
+ version = 0.5.51
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,235 @@
1
+ import unittest
2
+ from typing import List, Dict, Union
3
+
4
+ from util.simple_math import generate_rand_nums, round_to_level, bucket_series, bucketize_val
5
+
6
+ class SimpleMathTests(unittest.TestCase):
7
+
8
+ def test_generate_rand_nums(self):
9
+ range_min : float = 0
10
+ range_max : float = 1
11
+ size : int = 100
12
+ percentage_in_range : float = 91
13
+ abs_min : float = -0.5
14
+ abs_max : float = 1.1
15
+
16
+ rand_nums : List[float] = generate_rand_nums(
17
+ range_min = range_min,
18
+ range_max = range_max,
19
+ size = size,
20
+ percent_in_range = percentage_in_range,
21
+ abs_min = abs_min,
22
+ abs_max = abs_max
23
+ )
24
+
25
+ assert(len(rand_nums)==size)
26
+ assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
27
+ assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
28
+
29
+
30
+ range_min = -1
31
+ range_max = 1
32
+ percentage_in_range = 91
33
+ abs_min = -1.5
34
+ abs_max = 1.5
35
+
36
+ rand_nums : List[float] = generate_rand_nums(
37
+ range_min = range_min,
38
+ range_max = range_max,
39
+ size = size,
40
+ percent_in_range = percentage_in_range,
41
+ abs_min = abs_min,
42
+ abs_max = abs_max
43
+ )
44
+
45
+ assert(len(rand_nums)==size)
46
+ assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
47
+ assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
48
+
49
+
50
+ range_min = 0
51
+ range_max = 100
52
+ percentage_in_range = 91
53
+ abs_min = -150
54
+ abs_max = 150
55
+
56
+ rand_nums : List[float] = generate_rand_nums(
57
+ range_min = range_min,
58
+ range_max = range_max,
59
+ size = size,
60
+ percent_in_range = percentage_in_range,
61
+ abs_min = abs_min,
62
+ abs_max = abs_max
63
+ )
64
+
65
+ assert(len(rand_nums)==size)
66
+ assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
67
+ assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
68
+
69
+
70
+ range_min = -100
71
+ range_max = 100
72
+ percentage_in_range = 91
73
+ abs_min = -150
74
+ abs_max = 150
75
+
76
+ rand_nums : List[float] = generate_rand_nums(
77
+ range_min = range_min,
78
+ range_max = range_max,
79
+ size = size,
80
+ percent_in_range = percentage_in_range,
81
+ abs_min = abs_min,
82
+ abs_max = abs_max
83
+ )
84
+
85
+ assert(len(rand_nums)==size)
86
+ assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
87
+ assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
88
+
89
+ def test_round_to_level(self):
90
+ prices = [
91
+ { 'price' : 15080, 'rounded' : 15000},
92
+ { 'price' : 15180, 'rounded' : 15200},
93
+ { 'price' : 25080, 'rounded' : 25200},
94
+ { 'price' : 25180, 'rounded' : 25200},
95
+ { 'price' : 25380, 'rounded' : 25500},
96
+ { 'price' : 95332, 'rounded' : 95000},
97
+ { 'price' : 95878, 'rounded' : 96000},
98
+ { 'price' : 103499, 'rounded' : 103000},
99
+ { 'price' : 103500, 'rounded' : 104000},
100
+ { 'price' : 150800, 'rounded' : 150000},
101
+ { 'price' : 151800, 'rounded' : 152000}
102
+ ]
103
+ for entry in prices:
104
+ price = entry['price']
105
+ expected = entry['rounded']
106
+ rounded_price = round_to_level(price, level_granularity=0.01)
107
+ print(f"{price} rounded to: {rounded_price}")
108
+ assert(rounded_price==expected)
109
+
110
+ def test_bucket_series(self):
111
+
112
+ level_granularity : float = 0.1
113
+
114
+ range_min : float = 0
115
+ range_max : float = 1
116
+ size : int = 100
117
+ percentage_in_range : float = 91
118
+ abs_min : float = -0.5
119
+ abs_max : float = 1.1
120
+
121
+ rand_nums : List[float] = generate_rand_nums(
122
+ range_min = range_min,
123
+ range_max = range_max,
124
+ size = size,
125
+ percent_in_range = percentage_in_range,
126
+ abs_min = abs_min,
127
+ abs_max = abs_max
128
+ )
129
+
130
+ buckets : Dict[
131
+ str,
132
+ Dict[str,Union[float, List[float]]]
133
+ ] = bucket_series(
134
+ values = rand_nums,
135
+ outlier_threshold_percent = 10,
136
+ level_granularity=level_granularity
137
+ )
138
+
139
+ bucketized = []
140
+ for num in rand_nums:
141
+ bucketized.append(
142
+ bucketize_val(num, buckets=buckets)
143
+ )
144
+
145
+
146
+ range_min = -1
147
+ range_max = 1
148
+ size : int = 100
149
+ percentage_in_range = 91
150
+ abs_min = -1.5
151
+ abs_max = 1.5
152
+
153
+ rand_nums : List[float] = generate_rand_nums(
154
+ range_min = range_min,
155
+ range_max = range_max,
156
+ size = size,
157
+ percent_in_range = percentage_in_range,
158
+ abs_min = abs_min,
159
+ abs_max = abs_max
160
+ )
161
+
162
+ buckets = bucket_series(
163
+ values = rand_nums,
164
+ outlier_threshold_percent = 10,
165
+ level_granularity=level_granularity
166
+ )
167
+
168
+
169
+ range_min = 0
170
+ range_max = 100
171
+ size : int = 100
172
+ percentage_in_range = 91
173
+ abs_min = -0.5
174
+ abs_max = 150
175
+
176
+ rand_nums : List[float] = generate_rand_nums(
177
+ range_min = range_min,
178
+ range_max = range_max,
179
+ size = size,
180
+ percent_in_range = percentage_in_range,
181
+ abs_min = abs_min,
182
+ abs_max = abs_max
183
+ )
184
+
185
+ buckets = bucket_series(
186
+ values = rand_nums,
187
+ outlier_threshold_percent = 10,
188
+ level_granularity=level_granularity
189
+ )
190
+
191
+
192
+ range_min = -100
193
+ range_max = 100
194
+ size : int = 100
195
+ percentage_in_range = 91
196
+ abs_min = -150
197
+ abs_max = 150
198
+
199
+ rand_nums : List[float] = generate_rand_nums(
200
+ range_min = range_min,
201
+ range_max = range_max,
202
+ size = size,
203
+ percent_in_range = percentage_in_range,
204
+ abs_min = abs_min,
205
+ abs_max = abs_max
206
+ )
207
+
208
+ buckets = bucket_series(
209
+ values = rand_nums,
210
+ outlier_threshold_percent = 10,
211
+ level_granularity=level_granularity
212
+ )
213
+
214
+
215
+ range_min = 20_000
216
+ range_max = 120_000
217
+ size : int = 100
218
+ percentage_in_range = 91
219
+ abs_min = 15_000
220
+ abs_max = 130_000
221
+
222
+ rand_nums : List[float] = generate_rand_nums(
223
+ range_min = range_min,
224
+ range_max = range_max,
225
+ size = size,
226
+ percent_in_range = percentage_in_range,
227
+ abs_min = abs_min,
228
+ abs_max = abs_max
229
+ )
230
+
231
+ buckets = bucket_series(
232
+ values = rand_nums,
233
+ outlier_threshold_percent = 10,
234
+ level_granularity=level_granularity
235
+ )
@@ -63,24 +63,3 @@ class TradingUtilTests(unittest.TestCase):
63
63
  default_effective_tp_trailing_percent = default_effective_tp_trailing_percent
64
64
  )
65
65
  assert(effective_tp_trailing_percent==0) # Most tight trailing SL
66
-
67
- def test_round_to_level(self):
68
- prices = [
69
- { 'price' : 15080, 'rounded' : 15000},
70
- { 'price' : 15180, 'rounded' : 15200},
71
- { 'price' : 25080, 'rounded' : 25200},
72
- { 'price' : 25180, 'rounded' : 25200},
73
- { 'price' : 25380, 'rounded' : 25500},
74
- { 'price' : 95332, 'rounded' : 95000},
75
- { 'price' : 95878, 'rounded' : 96000},
76
- { 'price' : 103499, 'rounded' : 103000},
77
- { 'price' : 103500, 'rounded' : 104000},
78
- { 'price' : 150800, 'rounded' : 150000},
79
- { 'price' : 151800, 'rounded' : 152000}
80
- ]
81
- for entry in prices:
82
- price = entry['price']
83
- expected = entry['rounded']
84
- rounded_price = round_to_level(price, level_granularity=0.01)
85
- print(f"{price} rounded to: {rounded_price}")
86
- assert(rounded_price==expected)
@@ -11,6 +11,7 @@ from hurst import compute_Hc # compatible with pypy
11
11
  from ccxt.base.exchange import Exchange as CcxtExchange
12
12
  from ccxt import deribit
13
13
 
14
+ from siglab_py.util.simple_math import bucket_series
14
15
  from siglab_py.util.market_data_util import fix_column_types
15
16
  from siglab_py.constants import TrendDirection
16
17
 
@@ -473,6 +474,15 @@ def compute_candles_stats(
473
474
 
474
475
  lo_rs = lo_ma_up / lo_ma_down
475
476
  pd_candles.loc[:,'rsi'] = 100 - (100/(1 + lo_rs))
477
+ rsi_buckets = bucket_series(
478
+ values = pd_candles['rsi'].to_list(),
479
+ outlier_threshold_percent=10,
480
+ level_granularity=0.1
481
+ )
482
+
483
+ pd_candles['rsi_bucket'] = pd_candles['rsi'].rolling(
484
+ window=sliding_window_how_many_candles
485
+ ).apply(lambda x: bucketize_val(x, buckets=rsi_buckets))
476
486
  pd_candles['ema_rsi'] = pd_candles['rsi'].ewm(
477
487
  span=rsi_sliding_window_how_many_candles,
478
488
  adjust=False).mean()
@@ -0,0 +1,205 @@
1
+ import math
2
+ import random
3
+ from typing import List, Dict, Union
4
+
5
+ def generate_rand_nums(
6
+ range_min : float = 0,
7
+ range_max : float = 1,
8
+ size=100, # list size
9
+ percent_in_range : float = 100,
10
+ abs_min : float = 0,
11
+ abs_max : float = 1
12
+ ) -> List[float]:
13
+ assert(range_min<range_max)
14
+
15
+ if abs_min>range_min:
16
+ abs_min = range_min
17
+ if abs_max<range_max:
18
+ abs_max = range_max
19
+
20
+ result : List[float] = []
21
+ for _ in range(int(size * percent_in_range/100)):
22
+ result.append(random.uniform(range_min, range_max))
23
+ for _ in range(size - len(result)):
24
+ if random.uniform(0, 1)>0.5:
25
+ result.append(random.uniform(abs_min, range_min))
26
+ else:
27
+ result.append(random.uniform(range_max, abs_max))
28
+
29
+ random.shuffle(result)
30
+
31
+ return result
32
+
33
+ # https://norman-lm-fung.medium.com/levels-are-psychological-7176cdefb5f2
34
+ def round_to_level(
35
+ num : float,
36
+ level_granularity : float = 0.01
37
+ ) -> float:
38
+ level_size = num * level_granularity
39
+ magnitude = math.floor(math.log10(level_size))
40
+ base_increment = 10 ** magnitude
41
+ rounded_level_size = round(level_size / base_increment) * base_increment
42
+ rounded_num = round(num / rounded_level_size) * rounded_level_size
43
+ return rounded_num
44
+
45
+ def bucket_series(
46
+ values : List[float],
47
+ outlier_threshold_percent : float = 0,
48
+ level_granularity : float = 0.1 # 0.1 = 10%
49
+ ) -> Dict[
50
+ str,
51
+ Dict[str,Union[float, List[float]]]
52
+ ]:
53
+ buckets : Dict[
54
+ str,
55
+ Dict[str,Union[float, List[float]]]
56
+ ] = {}
57
+ list_0_to_1 : bool = True if len([x for x in values if x<0 or x>1])/len(values)*100 <= outlier_threshold_percent else False
58
+ list_m1_to_1 : bool = True if len([x for x in values if x<-1 or x>1])/len(values)*100 <= outlier_threshold_percent else False
59
+ list_0_to_100 : bool = True if len([x for x in values if x<0 or x>100])/len(values)*100 <= outlier_threshold_percent else False
60
+ list_m100_to_100 : bool = True if len([x for x in values if x<-100 or x>100])/len(values)*100 <= outlier_threshold_percent else False
61
+
62
+ def _generate_sequence(start, stop, step):
63
+ result = []
64
+ current = start
65
+ num_steps = int((stop - start) / step) + 1
66
+ for i in range(num_steps):
67
+ result.append(round(start + i * step, 10))
68
+ return result
69
+
70
+ if list_0_to_1:
71
+ intervals = _generate_sequence(0.1, 1, 0.1)
72
+ last_interval = 0
73
+ buckets[f"< 0"] = {
74
+ 'min' : float("-inf"),
75
+ 'max' : 0,
76
+ 'values' : [ x for x in values if x<0 ]
77
+ }
78
+ for interval in intervals:
79
+ buckets[f"{last_interval} - {interval}"] = {
80
+ 'min' : last_interval,
81
+ 'max' : interval,
82
+ 'values' : [ x for x in values if x>=last_interval and x<interval ]
83
+ }
84
+ last_interval = interval
85
+ buckets[f">1"] = {
86
+ 'min' : last_interval,
87
+ 'max' : float("inf"),
88
+ 'values' : [ x for x in values if x>=1 ]
89
+ }
90
+
91
+ elif not list_0_to_1 and list_m1_to_1:
92
+ intervals = _generate_sequence(-0.9, 1, 0.1)
93
+ last_interval = -1
94
+ buckets[f"< -1"] = {
95
+ 'min' : float("-inf"),
96
+ 'max' : -1,
97
+ 'values' : [ x for x in values if x<-1 ]
98
+ }
99
+ for interval in intervals:
100
+ buckets[f"{last_interval} - {interval}"] = {
101
+ 'min' : last_interval,
102
+ 'max' : interval,
103
+ 'values' : [ x for x in values if x>=last_interval and x<interval ]
104
+ }
105
+ last_interval = interval
106
+ buckets[f">1"] = {
107
+ 'min' : last_interval,
108
+ 'max' : float("inf"),
109
+ 'values' : [ x for x in values if x>=1 ]
110
+ }
111
+
112
+ elif not list_0_to_1 and not list_m1_to_1 and list_0_to_100:
113
+ intervals = _generate_sequence(10, 100, 10)
114
+ last_interval = 0
115
+ buckets[f"<0"] = {
116
+ 'min' : float("-inf"),
117
+ 'max' : 0,
118
+ 'values' : [ x for x in values if x<0 ]
119
+ }
120
+ for interval in intervals:
121
+ buckets[f"{last_interval} - {interval}"] = {
122
+ 'min' : last_interval,
123
+ 'max' : interval,
124
+ 'values' : [ x for x in values if x>=last_interval and x<interval ]
125
+ }
126
+ last_interval = interval
127
+ buckets[f">100"] = {
128
+ 'min' : last_interval,
129
+ 'max' : float("inf"),
130
+ 'values' : [ x for x in values if x>=100 ]
131
+ }
132
+
133
+ elif not list_0_to_1 and not list_m1_to_1 and not list_0_to_100 and list_m100_to_100:
134
+ intervals = _generate_sequence(-90, 100, 10)
135
+ last_interval = -100
136
+ buckets[f"<-100"] = {
137
+ 'min' : float("-inf"),
138
+ 'max' : -100,
139
+ 'values' : [ x for x in values if x<-100 ]
140
+ }
141
+ for interval in intervals:
142
+ buckets[f"{last_interval} - {interval}"] = {
143
+ 'min' : last_interval,
144
+ 'max' : interval,
145
+ 'values' : [ x for x in values if x>=last_interval and x<interval ]
146
+ }
147
+ last_interval = interval
148
+ buckets[f">100"] = {
149
+ 'min' : last_interval,
150
+ 'max' : float("inf"),
151
+ 'values' : [ x for x in values if x>=100 ]
152
+ }
153
+
154
+ else:
155
+ range_min = round_to_level(
156
+ min(values),
157
+ level_granularity=level_granularity
158
+ )
159
+ range_max = round_to_level(
160
+ max(values),
161
+ level_granularity=level_granularity
162
+ )
163
+ step = round_to_level(
164
+ abs(range_max - range_min) * level_granularity,
165
+ level_granularity=level_granularity
166
+ )
167
+
168
+ intervals = _generate_sequence(range_min+step, range_max, step)
169
+ last_interval = range_min
170
+ buckets[f"< {range_min}"] = {
171
+ 'min' : float("-inf"),
172
+ 'max' : range_min,
173
+ 'values' : [ x for x in values if x<range_min ]
174
+ }
175
+ for interval in intervals:
176
+ buckets[f"{last_interval} - {interval}"] = {
177
+ 'min' : last_interval,
178
+ 'max' : interval,
179
+ 'values' : [ x for x in values if x>=last_interval and x<interval ]
180
+ }
181
+ last_interval = interval
182
+ buckets[f"> {range_max}"] = {
183
+ 'min' : last_interval,
184
+ 'max' : float("inf"),
185
+ 'values' : [ x for x in values if x>=range_max ]
186
+ }
187
+
188
+ for key in buckets:
189
+ bucket = buckets[key]
190
+ assert(len([x for x in bucket['values'] if x<bucket['min'] or x>bucket['max']])==0) # type: ignore
191
+
192
+ return buckets
193
+
194
+ def bucketize_val(
195
+ x : float,
196
+ buckets : Dict[
197
+ str,
198
+ Dict[str,Union[float, List[float]]]
199
+ ]
200
+ ) -> Union[str,None]:
201
+ for key in buckets:
202
+ bucket = buckets[key]
203
+ if x>=bucket['min'] and x<=bucket['max']: # type: ignore
204
+ return key
205
+ return None
@@ -116,15 +116,3 @@ def calc_eff_trailing_sl(
116
116
  effective_tp_trailing_percent = default_effective_tp_trailing_percent
117
117
 
118
118
  return effective_tp_trailing_percent
119
-
120
- # https://norman-lm-fung.medium.com/levels-are-psychological-7176cdefb5f2
121
- def round_to_level(
122
- price : float,
123
- level_granularity : float = 0.01
124
- ) -> float:
125
- level_size = price * level_granularity
126
- magnitude = math.floor(math.log10(level_size))
127
- base_increment = 10 ** magnitude
128
- rounded_level_size = round(level_size / base_increment) * base_increment
129
- rounded_price = round(price / rounded_level_size) * rounded_level_size
130
- return rounded_price
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siglab_py
3
- Version: 0.5.48
3
+ Version: 0.5.51
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,87 +0,0 @@
1
- import unittest
2
- from typing import List
3
-
4
- from util.simple_math import generate_rand_nums
5
-
6
- class SimpleMathTests(unittest.TestCase):
7
-
8
- def test_generate_rand_nums(self):
9
- range_min : float = 0
10
- range_max : float = 1
11
- size : int = 100
12
- percentage_in_range : float = 91
13
- abs_min : float = -0.5
14
- abs_max : float = 1.1
15
-
16
- rand_nums : List[float] = generate_rand_nums(
17
- range_min = range_min,
18
- range_max = range_max,
19
- size = size,
20
- percent_in_range = percentage_in_range,
21
- abs_min = abs_min,
22
- abs_max = abs_max
23
- )
24
-
25
- assert(len(rand_nums)==size)
26
- assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
27
- assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
28
-
29
-
30
- range_min = -1
31
- range_max = 1
32
- percentage_in_range = 91
33
- abs_min = -1.5
34
- abs_max = 1.5
35
-
36
- rand_nums : List[float] = generate_rand_nums(
37
- range_min = range_min,
38
- range_max = range_max,
39
- size = size,
40
- percent_in_range = percentage_in_range,
41
- abs_min = abs_min,
42
- abs_max = abs_max
43
- )
44
-
45
- assert(len(rand_nums)==size)
46
- assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
47
- assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
48
-
49
-
50
- range_min = 0
51
- range_max = 100
52
- percentage_in_range = 91
53
- abs_min = -150
54
- abs_max = 150
55
-
56
- rand_nums : List[float] = generate_rand_nums(
57
- range_min = range_min,
58
- range_max = range_max,
59
- size = size,
60
- percent_in_range = percentage_in_range,
61
- abs_min = abs_min,
62
- abs_max = abs_max
63
- )
64
-
65
- assert(len(rand_nums)==size)
66
- assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
67
- assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
68
-
69
-
70
- range_min = -100
71
- range_max = 100
72
- percentage_in_range = 91
73
- abs_min = -150
74
- abs_max = 150
75
-
76
- rand_nums : List[float] = generate_rand_nums(
77
- range_min = range_min,
78
- range_max = range_max,
79
- size = size,
80
- percent_in_range = percentage_in_range,
81
- abs_min = abs_min,
82
- abs_max = abs_max
83
- )
84
-
85
- assert(len(rand_nums)==size)
86
- assert(len([x for x in rand_nums if x>=range_min and x<=range_max]) == (percentage_in_range/100) * size)
87
- assert(len([x for x in rand_nums if x<abs_min or x>abs_max]) == 0)
@@ -1,30 +0,0 @@
1
- import random
2
- from typing import List
3
-
4
- def generate_rand_nums(
5
- range_min : float = 0,
6
- range_max : float = 1,
7
- size=100, # list size
8
- percent_in_range : float = 100,
9
- abs_min : float = 0,
10
- abs_max : float = 1
11
- ):
12
- assert(range_min<range_max)
13
-
14
- if abs_min>range_min:
15
- abs_min = range_min
16
- if abs_max<range_max:
17
- abs_max = range_max
18
-
19
- result = []
20
- for _ in range(int(size * percent_in_range/100)):
21
- result.append(random.uniform(range_min, range_max))
22
- for _ in range(size - len(result)):
23
- if random.uniform(0, 1)>0.5:
24
- result.append(random.uniform(abs_min, range_min))
25
- else:
26
- result.append(random.uniform(range_max, abs_max))
27
-
28
- random.shuffle(result)
29
-
30
- return result