Qubx 0.2.69__tar.gz → 0.2.70__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 Qubx might be problematic. Click here for more details.
- {qubx-0.2.69 → qubx-0.2.70}/PKG-INFO +1 -1
- {qubx-0.2.69 → qubx-0.2.70}/pyproject.toml +1 -1
- qubx-0.2.70/src/qubx/gathering/simplest.py +88 -0
- qubx-0.2.69/src/qubx/gathering/simplest.py +0 -44
- {qubx-0.2.69 → qubx-0.2.70}/README.md +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/build.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/_nb_magic.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/backtester/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/backtester/ome.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/backtester/optimization.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/backtester/queue.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/backtester/simulator.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/account.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/basics.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/context.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/exceptions.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/helpers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/loggers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/lookups.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/metrics.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/series.pxd +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/series.pyi +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/series.pyx +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/strategy.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/utils.pyi +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/core/utils.pyx +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/data/helpers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/data/readers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/impl/ccxt_connector.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/impl/ccxt_customizations.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/impl/ccxt_trading.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/impl/ccxt_utils.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/math/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/math/stats.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/pandaz/ta.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/pandaz/utils.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/ta/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/trackers/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/trackers/composite.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/trackers/sizers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/__init__.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/charting/lookinglass.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/misc.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/ntp.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/runner.py +0 -0
- {qubx-0.2.69 → qubx-0.2.70}/src/qubx/utils/time.py +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from qubx import logger
|
|
2
|
+
from qubx.core.basics import Deal, Instrument, TargetPosition
|
|
3
|
+
from qubx.core.strategy import IPositionGathering, StrategyContext
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SimplePositionGatherer(IPositionGathering):
|
|
7
|
+
"""
|
|
8
|
+
Default implementation of positions gathering by single orders through strategy context
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
entry_order_id: str | None = None
|
|
12
|
+
|
|
13
|
+
def _cncl_order(self, ctx: StrategyContext, instrument: Instrument) -> None:
|
|
14
|
+
if self.entry_order_id:
|
|
15
|
+
logger.debug(
|
|
16
|
+
f"<green>{instrument.symbol}</green>: Cancelling previous entry order <red>{self.entry_order_id}</red>"
|
|
17
|
+
)
|
|
18
|
+
try:
|
|
19
|
+
ctx.cancel_order(self.entry_order_id)
|
|
20
|
+
except Exception as e:
|
|
21
|
+
logger.error(f"Cancelling entry order failed: {str(e)}")
|
|
22
|
+
self.entry_order_id = None
|
|
23
|
+
|
|
24
|
+
def alter_position_size(self, ctx: StrategyContext, target: TargetPosition) -> float:
|
|
25
|
+
# Here is default inplementation:
|
|
26
|
+
# just trade it through the strategy context by using market (or limit) orders.
|
|
27
|
+
# but in general it may have complex logic for position adjustment
|
|
28
|
+
instrument, new_size, at_price = target.instrument, target.target_position_size, target.price
|
|
29
|
+
current_position = ctx.positions[instrument.symbol].quantity
|
|
30
|
+
to_trade = new_size - current_position
|
|
31
|
+
|
|
32
|
+
# - first cancel previous entry order if exists
|
|
33
|
+
self._cncl_order(ctx, instrument)
|
|
34
|
+
|
|
35
|
+
if abs(to_trade) < instrument.min_size:
|
|
36
|
+
if current_position != 0:
|
|
37
|
+
logger.warning(
|
|
38
|
+
f"{instrument.exchange}:{instrument.symbol}: Unable change position from {current_position} to {new_size} : too small difference"
|
|
39
|
+
)
|
|
40
|
+
else:
|
|
41
|
+
|
|
42
|
+
# - check how it should be traded: market or limit or stop order
|
|
43
|
+
opts = {}
|
|
44
|
+
_is_stop_or_limit = False
|
|
45
|
+
if at_price:
|
|
46
|
+
# - we already havbe position but it's requested to change at a specific price
|
|
47
|
+
if abs(current_position) > instrument.min_size:
|
|
48
|
+
logger.warning(
|
|
49
|
+
f"<green>{instrument.symbol}</green>: Attempt to change current position {current_position} to {new_size} at {at_price} !"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
quote = ctx.quote(instrument.symbol)
|
|
53
|
+
if (to_trade > 0 and at_price > quote.ask) or (to_trade < 0 and at_price < quote.bid):
|
|
54
|
+
opts["stop_type"] = "market"
|
|
55
|
+
_is_stop_or_limit = True
|
|
56
|
+
|
|
57
|
+
if (to_trade > 0 and at_price <= quote.bid) or (to_trade < 0 and at_price >= quote.ask):
|
|
58
|
+
_is_stop_or_limit = True
|
|
59
|
+
|
|
60
|
+
r = ctx.trade(instrument, to_trade, at_price, **opts)
|
|
61
|
+
if _is_stop_or_limit:
|
|
62
|
+
self.entry_order_id = r.id
|
|
63
|
+
logger.debug(
|
|
64
|
+
f"<green>{instrument.symbol}</green>: Position may be adjusted from {current_position} to {new_size} at {at_price} : {r}"
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
self.entry_order_id = None
|
|
68
|
+
logger.debug(
|
|
69
|
+
f"<green>{instrument.symbol}</green>: Adjusting position from {current_position} to {new_size} : {r}"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
current_position = new_size
|
|
73
|
+
# - TODO: need to check how fast position is being updated on live
|
|
74
|
+
# current_position = ctx.positions[instrument.symbol].quantity
|
|
75
|
+
|
|
76
|
+
return current_position
|
|
77
|
+
|
|
78
|
+
def on_execution_report(self, ctx: StrategyContext, instrument: Instrument, deal: Deal):
|
|
79
|
+
if deal.order_id == self.entry_order_id:
|
|
80
|
+
self.entry_order_id = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class SplittedOrdersPositionGatherer(IPositionGathering):
|
|
84
|
+
"""
|
|
85
|
+
Gather position by splitting order into smaller parts randomly
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
pass
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
from qubx import logger
|
|
2
|
-
from qubx.core.basics import Deal, Instrument, TargetPosition
|
|
3
|
-
from qubx.core.strategy import IPositionGathering, StrategyContext
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class SimplePositionGatherer(IPositionGathering):
|
|
7
|
-
"""
|
|
8
|
-
Default implementation of positions gathering by single orders through strategy context
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
def alter_position_size(self, ctx: StrategyContext, target: TargetPosition) -> float:
|
|
12
|
-
instrument, new_size, at_price = target.instrument, target.target_position_size, target.price
|
|
13
|
-
current_position = ctx.positions[instrument.symbol].quantity
|
|
14
|
-
to_trade = new_size - current_position
|
|
15
|
-
if abs(to_trade) < instrument.min_size:
|
|
16
|
-
logger.warning(
|
|
17
|
-
f"{instrument.exchange}:{instrument.symbol}: Unable change position from {current_position} to {new_size} : too small difference"
|
|
18
|
-
)
|
|
19
|
-
else:
|
|
20
|
-
# - here is default inplementation:
|
|
21
|
-
# just trade it through the strategy context by using market (or limit) orders.
|
|
22
|
-
# - but in general it may have complex logic for position adjustment
|
|
23
|
-
r = ctx.trade(instrument, to_trade, at_price)
|
|
24
|
-
# , fill_at_price=target.signal.options.get("fill_at_signal_price", False)
|
|
25
|
-
logger.debug(
|
|
26
|
-
f"<green>{instrument.symbol}</green>: Adjusting position from {current_position} to {new_size} : {r}"
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
current_position = new_size
|
|
30
|
-
# - TODO: need to check how fast position is being updated on live
|
|
31
|
-
# current_position = ctx.positions[instrument.symbol].quantity
|
|
32
|
-
|
|
33
|
-
return current_position
|
|
34
|
-
|
|
35
|
-
def on_execution_report(self, ctx: StrategyContext, instrument: Instrument, deal: Deal):
|
|
36
|
-
pass
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class SplittedOrdersPositionGatherer(IPositionGathering):
|
|
40
|
-
"""
|
|
41
|
-
Gather position by splitting order into smaller parts randomly
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
pass
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|