Qubx 0.2.73__cp311-cp311-manylinux_2_35_x86_64.whl → 0.2.75__cp311-cp311-manylinux_2_35_x86_64.whl

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 Qubx might be problematic. Click here for more details.

@@ -90,7 +90,41 @@ def permutate_params(
90
90
  return _wrap_single_list(result) if wrap_as_list else result
91
91
 
92
92
 
93
- def variate(clz: Type[Any] | List[Type[Any]], *args, conditions=None, **kwargs) -> Dict[str, Any]:
93
+ def dicts_product(d1: dict, d2: dict) -> dict:
94
+ """
95
+ Product of two dictionaries.
96
+
97
+ Example:
98
+ -------
99
+
100
+ dicts_product({
101
+ 'A': 1,
102
+ 'B': 2,
103
+ }, {
104
+ 'C': 3,
105
+ 'D': 4,
106
+ })
107
+
108
+ Output:
109
+ ------
110
+ {
111
+ 'A + C': [1, 3],
112
+ 'A + D': [1, 4],
113
+ 'B + C': [2, 3],
114
+ 'B + D': [2, 4]
115
+ }
116
+
117
+ """
118
+ flatten = lambda l: [item for sublist in l for item in (sublist if isinstance(sublist, list) else [sublist])]
119
+ return {(a + " + " + b): flatten([d1[a], d2[b]]) for a, b in product(d1.keys(), d2.keys())}
120
+
121
+
122
+ class _dict(dict):
123
+ def __add__(self, other: dict) -> dict:
124
+ return _dict(dicts_product(self, other))
125
+
126
+
127
+ def variate(clz: Type[Any] | List[Type[Any]], *args, conditions=None, **kwargs) -> _dict:
94
128
  """
95
129
  Make variations of parameters for simulations (micro optimizer)
96
130
 
@@ -149,7 +183,9 @@ def variate(clz: Type[Any] | List[Type[Any]], *args, conditions=None, **kwargs)
149
183
  to_excl = [s for s, v in kwargs.items() if not isinstance(v, (list, set, tuple, range))]
150
184
  dic2str = lambda ds: [_cmprss(k) + "=" + str(v) for k, v in ds.items() if k not in to_excl]
151
185
 
152
- return {
153
- f"{sfx}_({ ','.join(dic2str(z)) })": _mk(clz, *args, **z)
154
- for z in permutate_params(kwargs, conditions=conditions)
155
- }
186
+ return _dict(
187
+ {
188
+ f"{sfx}_({ ','.join(dic2str(z)) })": _mk(clz, *args, **z)
189
+ for z in permutate_params(kwargs, conditions=conditions)
190
+ }
191
+ )
@@ -556,7 +556,7 @@ class SimulatedExchange(IBrokerServiceProvider):
556
556
  # we have to schedule possible crons before sending the data event itself
557
557
  if self._scheduler.check_and_run_tasks():
558
558
  # - push nothing - it will force to process last event
559
- cc.send((None, "time", None))
559
+ cc.send((None, "service_time", None))
560
560
 
561
561
  cc.send((symbol, data_type, data))
562
562
 
qubx/core/helpers.py CHANGED
@@ -300,9 +300,9 @@ class BasicScheduler:
300
300
  next_time = iter.get_next(start_time=start_time)
301
301
  if next_time:
302
302
  self._scdlr.enterabs(next_time, 1, self._trigger, (event, prev_time, next_time))
303
- logger.debug(
304
- f"Now is <red>{_SEC2TS(self.time_sec())}</red> next ({event}) at <cyan>{_SEC2TS(next_time)}</cyan>"
305
- )
303
+ # logger.debug(
304
+ # f"Now is <red>{_SEC2TS(self.time_sec())}</red> next ({event}) at <cyan>{_SEC2TS(next_time)}</cyan>"
305
+ # )
306
306
  return True
307
307
  logger.debug(f"({event}) task is not scheduled")
308
308
  return False
qubx/data/readers.py CHANGED
@@ -945,6 +945,23 @@ class QuestDBConnector(DataReader):
945
945
  return pd.Series()
946
946
  return vol_stats.set_index("symbol")["quote_volume"]
947
947
 
948
+ def get_fundamental_data(
949
+ self, exchange: str, start: str | pd.Timestamp | None = None, stop: str | pd.Timestamp | None = None
950
+ ) -> pd.DataFrame:
951
+ table_name = {"BINANCE.UM": "binance.umfutures.fundamental"}[exchange]
952
+ query = f"select * from {table_name}"
953
+ if start or stop:
954
+ conditions = []
955
+ if start:
956
+ conditions.append(f"timestamp >= '{start}'")
957
+ if stop:
958
+ conditions.append(f"timestamp < '{stop}'")
959
+ query += " where " + " and ".join(conditions)
960
+ df = self.execute(query)
961
+ if df.empty:
962
+ return pd.DataFrame()
963
+ return df.set_index(["timestamp", "symbol", "metric"]).value.unstack("metric")
964
+
948
965
  def get_names(self) -> List[str]:
949
966
  return self._get_names(self._builder)
950
967
 
@@ -1027,7 +1044,6 @@ class QuestDBSqlOrderBookBuilder(QuestDBSqlCandlesBuilder):
1027
1044
  Sql builder for snapshot data
1028
1045
  """
1029
1046
 
1030
- MAX_TIME_DELTA = pd.Timedelta("5h")
1031
1047
  SNAPSHOT_DELTA = pd.Timedelta("1h")
1032
1048
  MIN_DELTA = pd.Timedelta("1s")
1033
1049
 
@@ -1043,8 +1059,6 @@ class QuestDBSqlOrderBookBuilder(QuestDBSqlCandlesBuilder):
1043
1059
  raise ValueError("Start and end dates must be provided for orderbook data!")
1044
1060
  start_dt, end_dt = pd.Timestamp(start), pd.Timestamp(end)
1045
1061
  delta = end_dt - start_dt
1046
- if delta > self.MAX_TIME_DELTA:
1047
- raise ValueError(f"Time range is too big for orderbook data: {delta}, max allowed: {self.MAX_TIME_DELTA}")
1048
1062
 
1049
1063
  raw_start_dt = start_dt.floor(self.SNAPSHOT_DELTA) - self.MIN_DELTA
1050
1064
 
qubx/trackers/riskctrl.py CHANGED
@@ -5,7 +5,7 @@ from typing import Dict, List, Literal
5
5
  import numpy as np
6
6
 
7
7
  from qubx import logger
8
- from qubx.core.basics import Deal, Instrument, Signal, TargetPosition
8
+ from qubx.core.basics import Deal, Instrument, OrderStatus, Signal, TargetPosition
9
9
  from qubx.core.series import Bar, Quote, Trade
10
10
  from qubx.core.strategy import IPositionSizer, PositionsTracker, StrategyContext
11
11
  from qubx.trackers.sizers import FixedRiskSizer, FixedSizer
@@ -270,6 +270,15 @@ class BrokerSideRiskController(RiskController):
270
270
  )
271
271
  order = ctx.trade(instrument, -pos, c_w.target.take)
272
272
  c_w.take_order_id = order.id
273
+
274
+ # - if order was executed immediately we don't need to send stop order
275
+ if order.status == "CLOSED":
276
+ c_w.status = State.RISK_TRIGGERED
277
+ logger.debug(
278
+ f"<yellow>{self.__class__.__name__}</yellow> <g>TAKE PROFIT</g> was exected immediately for <green>{instrument.symbol}</green> at {c_w.target.take}"
279
+ )
280
+ return
281
+
273
282
  except Exception as e:
274
283
  logger.error(
275
284
  f"<yellow>{self.__class__.__name__}</yellow> couldn't send take limit order for <green>{instrument.symbol}</green>: {str(e)}"
qubx/utils/time.py CHANGED
@@ -113,7 +113,7 @@ def infer_series_frequency(series: Union[List, pd.DataFrame, pd.Series, pd.Datet
113
113
  [
114
114
  (
115
115
  x
116
- if isinstance(x, (np.timedelta64, int))
116
+ if isinstance(x, (np.timedelta64, int, np.int64))
117
117
  else int(x) if isinstance(x, float) else int(1e9 * x.total_seconds())
118
118
  )
119
119
  for x in np.abs(np.diff(times_index))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Qubx
3
- Version: 0.2.73
3
+ Version: 0.2.75
4
4
  Summary: Qubx - quantitative trading framework
5
5
  Home-page: https://github.com/dmarienko/Qubx
6
6
  Author: Dmitry Marienko
@@ -2,28 +2,28 @@ qubx/__init__.py,sha256=dIHcfXv3uDX-kJ6qRGrH5OUW7evnGFf6A2VsLQlr2jc,6047
2
2
  qubx/_nb_magic.py,sha256=vfV892I5rkA_Zbno5Dsl9osPTGiXTCV3afZRDrTlcOQ,1915
3
3
  qubx/backtester/__init__.py,sha256=g9K4pp4ieY4rRKE0eA_02LMo-c4vnk-QqtVn_ff9F5U,66
4
4
  qubx/backtester/ome.py,sha256=FmtRMDCeEo8ZZP-yLswLilX6zx6SjJeieMiaLS7zrn0,11145
5
- qubx/backtester/optimization.py,sha256=wn48ppzziiNTG37tipY4HfRpqLKl2Y5iVCVO6NsCKRM,6588
5
+ qubx/backtester/optimization.py,sha256=ATHoiEGwbDIk0-lbFIxvVDmH_f-vtS10YV41pfOTCBA,7297
6
6
  qubx/backtester/queue.py,sha256=ys9tHyrqx3NKbcoTAoOn0m0caIk5F0GpS2x7_sCikro,14997
7
- qubx/backtester/simulator.py,sha256=EIcJ1J5ZuQdlUndtHrjurgh2yJb13b7_GCXEvB-mbYw,38180
7
+ qubx/backtester/simulator.py,sha256=t4VBrE4lSqn2LfZddtZ6X5CZ9FfJe3xuZpF34R9bkF0,38188
8
8
  qubx/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  qubx/core/account.py,sha256=uIU-EUMuH5owWhHTmU1pZ0WrkQkiv9YiFqSZW9dFDK8,9066
10
10
  qubx/core/basics.py,sha256=WA6LrmCG1si6pfyvezLRkfts575912AhGJMVbwBWSa0,21802
11
11
  qubx/core/context.py,sha256=WnHsItJ1OQ2jD0cHbYOMQ9ck4txLTwtf8Dp-zCLsUww,37759
12
12
  qubx/core/exceptions.py,sha256=W1gG_0fE3o2EMGUfOeOl3vVJDp8Z1iHLv4iZ0ThNkTs,306
13
- qubx/core/helpers.py,sha256=JAB1kcKO8l--gxg9_W2BzWW1N4x72sicw1oBszKYcbo,12657
13
+ qubx/core/helpers.py,sha256=R-xi4lgmYvWpUARIYcbcrNrRlEap5wc-GQ5sE4riUxQ,12663
14
14
  qubx/core/loggers.py,sha256=zpehm2-RdKG1ISe6t3DiM3RrL_zzGni3YFcxfgDkV24,16575
15
15
  qubx/core/lookups.py,sha256=qGOSb2SIxmgVPGJFLJnPDI1P9hCzFMVipRDcVLUm8qk,14599
16
16
  qubx/core/metrics.py,sha256=pL1obxnk8I7bDF41bQcOZ7MDsq4Wmj6g5cRiV7cFZKQ,38657
17
- qubx/core/series.cpython-311-x86_64-linux-gnu.so,sha256=jm55CYg3uP6-aMJq9mmSxKasX2pVh2xn8s_ldj_Zxqg,779016
17
+ qubx/core/series.cpython-311-x86_64-linux-gnu.so,sha256=HwGNM0szT5qwZX6C2RS5W4kRqMtJhVpckokYeHnWMmM,779016
18
18
  qubx/core/series.pxd,sha256=kF7QeLFgCM-C2hDxVvJM97ZOmyw1v7JEI9WfPKtQ6xs,3002
19
19
  qubx/core/series.pyi,sha256=bRBWOaDUBe4Hm2SvraoVeT-n5NFLA92fi8ezrArx9nY,2831
20
20
  qubx/core/series.pyx,sha256=UhZsnT7R3-UED05Fnp3mGxr4RSdMpWAHB4lkcz46MFo,32598
21
21
  qubx/core/strategy.py,sha256=tTXhDbFTH63yj53mLgVEDBZxYOxC51prcsyXWkdTgLs,10991
22
- qubx/core/utils.cpython-311-x86_64-linux-gnu.so,sha256=fygnriORpmolJOVVtOMiYFmhEinJVRy5xvzwtlcoCJo,82504
22
+ qubx/core/utils.cpython-311-x86_64-linux-gnu.so,sha256=BKuT2LUOVCVEen9gT8XNhwKxmFjr1SEJXZyDqb16nZg,82504
23
23
  qubx/core/utils.pyi,sha256=DAjyRVPJSxK4Em-9wui2F0yYHfP5tI5DjKavXNOnHa8,276
24
24
  qubx/core/utils.pyx,sha256=-8ek58CrbqWZq0-OY7WSREsCXBoBeWrD_wEYbIBS9rI,1696
25
25
  qubx/data/helpers.py,sha256=A0NGzhpXYWD92-GeB8TghwMnR0NW8bjcNJOCXybQw3g,782
26
- qubx/data/readers.py,sha256=HzNkFI2W4Rkh2AZWsOnnsi9VlHmlBCKaigyMd0T0Jiw,39523
26
+ qubx/data/readers.py,sha256=2VgaHKpHg67qej0Ty6D9q-zLRKEMamQY5pEIIJJcAZw,40062
27
27
  qubx/gathering/simplest.py,sha256=Ez3YFZMKH3o0jV0Qbg1SuZiuFNs_5No_C7wZ6vOeqfo,3814
28
28
  qubx/impl/ccxt_connector.py,sha256=ja_0WJDyZfkzqhNvoV-c5CCg15YnbRIThxw0TTNdwcc,13066
29
29
  qubx/impl/ccxt_customizations.py,sha256=WUhDT9x2SYuFrOyBIbk2D9Q_U_5QZhtLomLq88Egf_c,6230
@@ -35,14 +35,14 @@ qubx/pandaz/__init__.py,sha256=Iw5uzicYGSC3FEKZ-W1O5-7cXq_P0kH11-EcXV0zZhs,175
35
35
  qubx/pandaz/ta.py,sha256=NthiiueUoqWGRcjovcKKThcCcdImZn3JRdWDA2vL28k,85075
36
36
  qubx/pandaz/utils.py,sha256=XB28Zwv3cXWbKFXbcV5QGj_d6w-i8Yo4LYkX8aPuCHo,19613
37
37
  qubx/ta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- qubx/ta/indicators.cpython-311-x86_64-linux-gnu.so,sha256=dmNDjvU0iziEYwvNhie4NnPHPiQjVllrsSgy3l8DuPg,576168
38
+ qubx/ta/indicators.cpython-311-x86_64-linux-gnu.so,sha256=GNi4LN7GZgIfQOSKMEW19CmctnUW84lulZkdLbwq7TM,576168
39
39
  qubx/ta/indicators.pxd,sha256=YzPDhbbNPmy3m4NafwIRF5sNFsmkq-MM1gbeAygtBwM,4007
40
40
  qubx/ta/indicators.pyi,sha256=mM_7ISmGQDgjhwxCoZXDw7Rm9fynQSYjevV7fRoLdNc,1683
41
41
  qubx/ta/indicators.pyx,sha256=GuxB63YApFnA9IWNJDbBt90J1sOoxTf3jDWYQ3uD9So,24306
42
42
  qubx/trackers/__init__.py,sha256=-Hmlc8Mpdi_t6kyeW4ZtmYkHzrULaIb6gUsAkhUxA-4,169
43
43
  qubx/trackers/composite.py,sha256=rYQCaxu4IKLf5sS3DCyUUJaSUQwbCy6UMoVjsS-481A,6222
44
44
  qubx/trackers/rebalancers.py,sha256=dp-jemxczT8ndkjjzljsIgGnnA6lZQhsf5c4YdmHKCw,6048
45
- qubx/trackers/riskctrl.py,sha256=N0CQeCHnL8OI1LST9CAVmyirKRfBbfXQcCjHt8DGSfI,22978
45
+ qubx/trackers/riskctrl.py,sha256=URRZmYgb1-jcW4RTb2QXUozTnBiGhFEWHtTEjaqow5Q,23491
46
46
  qubx/trackers/sizers.py,sha256=vh49p2I_5LxYfznOQxlM6f0K1wadgtz7y9NSxg3WdNQ,5953
47
47
  qubx/utils/__init__.py,sha256=AL2YibJ3tqBKsZZLUjM9N2J5yy-Kq__k_44oTODQ5sM,321
48
48
  qubx/utils/_pyxreloader.py,sha256=FyqGzfSpZGYziB8JYS5AP3cLRAvJSIPAKgwQn0E4YQ0,12017
@@ -52,7 +52,7 @@ qubx/utils/marketdata/binance.py,sha256=36dl4rxOAGTeY3uoONmiPanj8BkP0oBdDiH-URJJ
52
52
  qubx/utils/misc.py,sha256=Av0mhrPCy5NZRrRmjOAhTKusa8wVdL7vCQtEy9bVnz4,10450
53
53
  qubx/utils/ntp.py,sha256=LZo4FPVY3rqLUV9VWkLcZaPOpUDFC8Qleynmfggg9No,1758
54
54
  qubx/utils/runner.py,sha256=Czo01KUCc9Oj9TIcs03d6Qh7fOpQV5w8oH6UDZ6Yqn0,9539
55
- qubx/utils/time.py,sha256=ioIos3VLA-iYI8LiQIn2m-t0Y37CEQAHFw_-C9Uwo0o,5188
56
- qubx-0.2.73.dist-info/METADATA,sha256=BlQcsbjTxWaDsNFuQjg5cTRBC0xujx9TYobz8EfeXWQ,2573
57
- qubx-0.2.73.dist-info/WHEEL,sha256=MLOa6LysROdjgj4FVxsHitAnIh8Be2D_c9ZSBHKrz2M,110
58
- qubx-0.2.73.dist-info/RECORD,,
55
+ qubx/utils/time.py,sha256=fIVWYRmqRT1zkLIWy9jo_Fpfpc03S0sYyOcrHZcfF74,5198
56
+ qubx-0.2.75.dist-info/METADATA,sha256=yq_PoJL-wZQFfQ_Ccmci1z7MNvatP0NL79SIomC421U,2573
57
+ qubx-0.2.75.dist-info/WHEEL,sha256=MLOa6LysROdjgj4FVxsHitAnIh8Be2D_c9ZSBHKrz2M,110
58
+ qubx-0.2.75.dist-info/RECORD,,
File without changes