Qubx 0.2.63__tar.gz → 0.2.64__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.

Files changed (56) hide show
  1. {qubx-0.2.63 → qubx-0.2.64}/PKG-INFO +1 -1
  2. {qubx-0.2.63 → qubx-0.2.64}/pyproject.toml +1 -1
  3. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/metrics.py +5 -0
  4. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/charting/lookinglass.py +41 -53
  5. {qubx-0.2.63 → qubx-0.2.64}/README.md +0 -0
  6. {qubx-0.2.63 → qubx-0.2.64}/build.py +0 -0
  7. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/__init__.py +0 -0
  8. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/_nb_magic.py +0 -0
  9. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/backtester/__init__.py +0 -0
  10. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/backtester/ome.py +0 -0
  11. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/backtester/optimization.py +0 -0
  12. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/backtester/queue.py +0 -0
  13. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/backtester/simulator.py +0 -0
  14. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/__init__.py +0 -0
  15. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/account.py +0 -0
  16. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/basics.py +0 -0
  17. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/context.py +0 -0
  18. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/exceptions.py +0 -0
  19. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/helpers.py +0 -0
  20. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/loggers.py +0 -0
  21. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/lookups.py +0 -0
  22. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/series.pxd +0 -0
  23. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/series.pyi +0 -0
  24. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/series.pyx +0 -0
  25. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/strategy.py +0 -0
  26. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/utils.pyi +0 -0
  27. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/core/utils.pyx +0 -0
  28. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/data/helpers.py +0 -0
  29. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/data/readers.py +0 -0
  30. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/gathering/simplest.py +0 -0
  31. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/impl/ccxt_connector.py +0 -0
  32. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/impl/ccxt_customizations.py +0 -0
  33. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/impl/ccxt_trading.py +0 -0
  34. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/impl/ccxt_utils.py +0 -0
  35. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/math/__init__.py +0 -0
  36. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/math/stats.py +0 -0
  37. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/pandaz/__init__.py +0 -0
  38. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/pandaz/ta.py +0 -0
  39. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/pandaz/utils.py +0 -0
  40. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/ta/__init__.py +0 -0
  41. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/ta/indicators.pxd +0 -0
  42. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/ta/indicators.pyi +0 -0
  43. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/ta/indicators.pyx +0 -0
  44. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/trackers/__init__.py +0 -0
  45. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/trackers/composite.py +0 -0
  46. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/trackers/rebalancers.py +0 -0
  47. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/trackers/riskctrl.py +0 -0
  48. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/trackers/sizers.py +0 -0
  49. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/__init__.py +0 -0
  50. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/_pyxreloader.py +0 -0
  51. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  52. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/marketdata/binance.py +0 -0
  53. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/misc.py +0 -0
  54. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/ntp.py +0 -0
  55. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/runner.py +0 -0
  56. {qubx-0.2.63 → qubx-0.2.64}/src/qubx/utils/time.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Qubx
3
- Version: 0.2.63
3
+ Version: 0.2.64
4
4
  Summary: Qubx - quantitative trading framework
5
5
  Home-page: https://github.com/dmarienko/Qubx
6
6
  Author: Dmitry Marienko
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "Qubx"
3
- version = "0.2.63"
3
+ version = "0.2.64"
4
4
  description = "Qubx - quantitative trading framework"
5
5
  authors = ["Dmitry Marienko <dmitry@gmail.com>", "Yuriy Arabskyy <yuriy.arabskyy@gmail.com>"]
6
6
  readme = "README.md"
@@ -892,6 +892,7 @@ def chart_signals(
892
892
  overlay=[],
893
893
  info=True,
894
894
  show_trades: bool = True,
895
+ show_signals: bool = False,
895
896
  show_quantity: bool = False,
896
897
  show_value: bool = False,
897
898
  show_leverage: bool = True,
@@ -965,6 +966,10 @@ def chart_signals(
965
966
  ]
966
967
  overlay = list(overlay) + [excs]
967
968
 
969
+ if show_signals:
970
+ sigs = result.signals_log[result.signals_log["instrument_id"] == symbol]
971
+ overlay = list(overlay) + [sigs]
972
+
968
973
  chart = LookingGlass([bars, *overlay], indicators).look(start, end, title=symbol).hover(show_info=info, h=height)
969
974
  if not show_table:
970
975
  return chart.show()
@@ -544,6 +544,23 @@ class LookingGlassPlotly(AbstractLookingGlass):
544
544
  def __plt_series(self, y, zoom, study_name, k, row, col, plot_style="line"):
545
545
  _lbl = y.name if hasattr(y, "name") and y.name else ("%s_%d" % (study_name, k))
546
546
 
547
+ def _scatter(
548
+ xs: pd.Series, comments: pd.Series | None, name: str, marker: str, color: str, size: int = 11
549
+ ) -> None:
550
+ _args = dict(
551
+ x=xs.index,
552
+ y=xs,
553
+ mode="markers",
554
+ name=name,
555
+ text=comments,
556
+ marker={
557
+ "symbol": marker,
558
+ "size": size,
559
+ "color": color,
560
+ },
561
+ )
562
+ self.fig.add_trace(go.Scatter(**_args), row=row, col=col)
563
+
547
564
  if isinstance(y, pd.DataFrame):
548
565
  yy = y[zoom] if zoom else y
549
566
 
@@ -760,65 +777,36 @@ class LookingGlassPlotly(AbstractLookingGlass):
760
777
  elif self._frame_has_cols(y, ["Type", "Time", "Price", "PriceOccured"]):
761
778
  _bot = yy[yy.Type == "-"]
762
779
  _top = yy[yy.Type == "+"]
763
- self.fig.add_trace(
764
- go.Scatter(
765
- x=_bot.index,
766
- y=_bot.PriceOccured,
767
- mode="markers",
768
- name="B",
769
- marker={"symbol": "triangle-right"},
770
- ),
771
- row=row,
772
- col=col,
773
- )
774
780
 
775
- self.fig.add_trace(
776
- go.Scatter(
777
- x=_top.index,
778
- y=_top.PriceOccured,
779
- mode="markers",
780
- name="T",
781
- marker={"symbol": "triangle-right"},
782
- ),
783
- row=row,
784
- col=col,
785
- )
781
+ _scatter(_bot.PriceOccured, None, "B", "triangle-right", "#3cfa00", 12)
782
+ _scatter(_top.PriceOccured, None, "T", "triangle-right", "#3cfa00", 12)
786
783
 
787
- # executed signals from signal tester
784
+ # executions from executor's log
788
785
  elif self._frame_has_cols(y, ["exec_price", "quantity"]):
789
786
  _b_ords = yy[yy.quantity > 0]
790
787
  _s_ords = yy[yy.quantity < 0]
791
- self.fig.add_trace(
792
- go.Scatter(
793
- x=_b_ords.index,
794
- y=_b_ords.exec_price,
795
- mode="markers",
796
- name="BOT",
797
- marker={
798
- "symbol": "triangle-up",
799
- "size": 13,
800
- "color": "#3cfa00",
801
- },
802
- ),
803
- row=row,
804
- col=col,
805
- )
806
788
 
807
- self.fig.add_trace(
808
- go.Scatter(
809
- x=_s_ords.index,
810
- y=_s_ords.exec_price,
811
- mode="markers",
812
- name="SLD",
813
- marker={
814
- "symbol": "triangle-down",
815
- "size": 13,
816
- "color": "#20ffff",
817
- },
818
- ),
819
- row=row,
820
- col=col,
821
- )
789
+ _scatter(_b_ords.exec_price, None, "BOT", "triangle-up", "#3cfa00", 12)
790
+ _scatter(_s_ords.exec_price, None, "SLD", "triangle-down", "#20ffff", 12)
791
+
792
+ # 27-aug-2024: show generated signals from Qubx backtester
793
+ elif self._frame_has_cols(y, ["signal", "reference_price", "price", "take", "stop", "group", "comment"]):
794
+ _sel_price = lambda x: x["reference_price"].where(x["price"].isna(), x["price"])
795
+ _b_sigs = yy[yy.signal > 0]
796
+ _z_sigs = yy[yy.signal == 0]
797
+ _s_sigs = yy[yy.signal < 0]
798
+ # - Longs
799
+ _scatter(_sel_price(_b_sigs), _b_sigs["comment"], "LONG", "triangle-up-open-dot", "#3cfa00")
800
+ _scatter(_b_sigs[~_b_sigs["take"].isna()]["take"], None, "Take", "line-ew-open", "#3cfa00")
801
+ _scatter(_b_sigs[~_b_sigs["stop"].isna()]["stop"], None, "Stop", "line-ew-open", "#fa3c00")
802
+
803
+ # - Shorts
804
+ _scatter(_sel_price(_s_sigs), _s_sigs["comment"], "SHORTS", "triangle-down-open-dot", "#20ffff")
805
+ _scatter(_s_sigs[~_s_sigs["take"].isna()]["take"], None, "Take", "line-ew-open", "#3cfa00")
806
+ _scatter(_s_sigs[~_s_sigs["stop"].isna()]["stop"], None, "Stop", "line-ew-open", "#fa3c00")
807
+
808
+ # - Exits
809
+ _scatter(_sel_price(_z_sigs), _z_sigs["comment"], "EXITS", "circle-open-dot", "#ffffff")
822
810
 
823
811
  else:
824
812
  for _col in yy.columns:
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