backtrader-next 2.3.1__py3-none-any.whl → 2.3.3__py3-none-any.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.
@@ -216,10 +216,10 @@ class Eq(bt.Analyzer):
216
216
  s.loc['Duration'] = s.End - s.Start
217
217
 
218
218
  s.loc['Equity Start [$]'] = equity[0]
219
- s.loc['Equity Final [$]'] = equity[-1]
220
- s.loc['Equity Peak [$]'] = equity.max()
221
- s.loc['Commissions [$]'] = commissions
222
- s.loc['Cum Return [%]'] = np.round((equity[-1] - equity[0]) / equity[0] * 100, 4)
219
+ s.loc['Equity Final [$]'] = round(equity[-1], 4)
220
+ s.loc['Equity Peak [$]'] = round(equity.max(), 4)
221
+ s.loc['Commissions [$]'] = round(commissions, 4)
222
+ s.loc['Cum Return [%]'] = round((equity[-1] - equity[0]) / equity[0] * 100, 4)
223
223
  # c = ohlc_data.Close.values
224
224
  # s.loc['Buy & Hold Return [%]'] = (c[-1] - c[0]) / c[0] * 100 # long-only return
225
225
 
@@ -239,25 +239,25 @@ class Eq(bt.Analyzer):
239
239
  # Use abs() to handle negative equity ratios (losses) and apply sign back
240
240
  equity_ratio = equity[-1]/equity[0]
241
241
  cagr_value = (abs(equity_ratio) ** (1/num_years) - 1) * np.sign(equity_ratio) if equity_ratio != 0 else 0
242
- s.loc['CAGR [%]'] = np.round(cagr_value, 4) * 100
242
+ s.loc['CAGR [%]'] = round(cagr_value, 4) * 100
243
243
 
244
244
  # Sharpe Ratio using arithmetic mean of returns to align with standard definition.
245
245
  # See: https://en.wikipedia.org/wiki/Sharpe_ratio
246
246
  mean_daily_return = day_returns.mean()
247
247
  annualized_mean_return = mean_daily_return * annual_trading_days
248
- s.loc['Sharpe Ratio'] = sharpe = np.round((annualized_mean_return * 100 - risk_free_rate * 100) / (
248
+ s.loc['Sharpe Ratio'] = sharpe = round((annualized_mean_return * 100 - risk_free_rate * 100) / (
249
249
  volatility if volatility != 0 else np.nan), 4)
250
250
 
251
251
  # Smart Sharpe Ratio
252
252
  skew = day_returns.skew()
253
253
  kurt = day_returns.kurt() # Excess kurtosis
254
- s.loc['Skew'] = np.round(skew, 4)
255
- s.loc['Kurtosis'] = np.round(kurt, 4)
254
+ s.loc['Skew'] = round(skew, 4)
255
+ s.loc['Kurtosis'] = round(kurt, 4)
256
256
  # Smart Sharpe Ratio is a modification of the Sharpe Ratio that accounts for skewness
257
257
  # and kurtosis of the returns distribution. It is defined as:
258
258
  # Smart Sharpe Ratio = Sharpe Ratio * (1 + (Skewness / 6) * Sharpe Ratio - (Kurtosis / 24) * (Sharpe Ratio ** 2))
259
259
  # See: https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/smart-sharpe-ratio
260
- s.loc['Smart Sharpe Ratio'] = np.round(sharpe * (1 + (skew / 6) * sharpe - (kurt / 24) * (sharpe ** 2)), 4)
260
+ s.loc['Smart Sharpe Ratio'] = round(sharpe * (1 + (skew / 6) * sharpe - (kurt / 24) * (sharpe ** 2)), 4)
261
261
 
262
262
  # Our Sortino mismatches `empyrical.sortino_ratio()` because they use arithmetic mean return
263
263
  _downside_returns = day_returns.clip(-np.inf, 0)
@@ -267,7 +267,7 @@ class Eq(bt.Analyzer):
267
267
  s.loc['Sortino Ratio'] = round(sortino_ratio, 4) if not np.isnan(sortino_ratio) else np.nan
268
268
 
269
269
  # s.loc['VWR Ratio'] = calc_vwr(eq_days=equity_df['Equity'].resample('D').last().dropna().to_numpy())
270
- s.loc['VWR Ratio'] = np.round(calc_vwr(eq_days=day_eq.to_numpy()), 4)
270
+ s.loc['VWR Ratio'] = round(calc_vwr(eq_days=day_eq.to_numpy()), 4)
271
271
  max_dd = -np.nan_to_num(dd_df.max())
272
272
  s.loc['Calmar Ratio'] = round((annualized_return * 100) / abs(max_dd), 4) if max_dd != 0 else np.nan
273
273
 
backtrader_next/broker.py CHANGED
@@ -19,10 +19,12 @@
19
19
  #
20
20
  ###############################################################################
21
21
  from __future__ import (absolute_import, division, print_function, unicode_literals)
22
+ from collections import defaultdict
22
23
 
23
24
  from backtrader_next.comminfo import CommInfoBase
24
25
  from backtrader_next.metabase import MetaParams
25
- from backtrader_next.utils.py3 import with_metaclass
26
+
27
+ from .utils.py3 import with_metaclass, iteritems
26
28
 
27
29
  from . import fillers as fillers
28
30
  from . import fillers as filler
@@ -52,7 +54,7 @@ class BrokerBase(with_metaclass(MetaBroker, object)):
52
54
 
53
55
  def __init__(self):
54
56
  self.comminfo = dict()
55
- self.state = dict()
57
+ self.info = defaultdict(dict)
56
58
  self.init()
57
59
 
58
60
  def init(self):
@@ -66,6 +68,13 @@ class BrokerBase(with_metaclass(MetaBroker, object)):
66
68
  def stop(self):
67
69
  pass
68
70
 
71
+ def add_info(self, strat_name:str, **kwargs):
72
+ '''Add the keys, values of kwargs to the internal info dictionary to
73
+ hold custom information in the broker
74
+ '''
75
+ for key, val in iteritems(kwargs):
76
+ self.info[strat_name][key] = val
77
+
69
78
  def add_order_history(self, orders, notify=False):
70
79
  '''Add order history. See cerebro for details'''
71
80
  raise NotImplementedError
backtrader_next/order.py CHANGED
@@ -707,16 +707,15 @@ class Order(OrderBase):
707
707
  del params['_owner_classname']
708
708
  params['restored'] = True
709
709
  ordtype = odict.get('ordtype', None)
710
- ord = None
710
+ new_ord = None
711
711
  if ordtype is None:
712
- ord = Order(**params)
712
+ new_ord = Order(**params)
713
713
  if ordtype == cls.Buy:
714
- ord = BuyOrder(**params)
714
+ new_ord = BuyOrder(**params)
715
715
  elif ordtype == cls.Sell:
716
- ord = SellOrder(**params)
716
+ new_ord = SellOrder(**params)
717
717
  else:
718
- ord = Order(**params)
719
-
718
+ new_ord = Order(**params)
720
719
  for key, val in odict.items():
721
720
  if key in ('created', 'executed'):
722
721
  odata = OrderData(
@@ -736,21 +735,21 @@ class Order(OrderBase):
736
735
  odata.psize = val.get('psize', 0)
737
736
  odata.pprice = val.get('pprice', 0.0)
738
737
  if key == 'created':
739
- ord.created = odata
738
+ new_ord.created = odata
740
739
  else:
741
- ord.executed = odata
740
+ new_ord.executed = odata
742
741
  elif key in ('ordtype', 'params'):
743
742
  pass # already handled
744
743
  elif key == 'info':
745
744
  for ik, iv in val.items():
746
- ord.info[ik] = iv
745
+ new_ord.info[ik] = iv
747
746
  elif key == 'comminfo':
748
- ord.comminfo = None
747
+ new_ord.comminfo = None
749
748
  elif key == 'parent':
750
- ord.parent = None
751
- elif hasattr(ord, key):
752
- setattr(ord, key, val)
753
- return ord
749
+ new_ord.parent = None
750
+ elif hasattr(new_ord, key):
751
+ setattr(new_ord, key, val)
752
+ return new_ord
754
753
 
755
754
 
756
755
  class BuyOrder(Order):
@@ -1,4 +1,4 @@
1
- #!/usr/bin389/env python
1
+ #!/usr/bin/env python
2
2
  # -*- coding: utf-8; py-indent-offset:4 -*-
3
3
  ###############################################################################
4
4
  #
@@ -118,6 +118,17 @@ class Strategy(with_metaclass(MetaStrategy, StrategyBase)):
118
118
  # keep the latest delivered data date in the line
119
119
  lines = ('datetime',)
120
120
 
121
+ def add_info(self, strat_name:str, **kwargs):
122
+ '''Add the keys, values of kwargs to the internal info dictionary to
123
+ hold custom information in the broker
124
+ '''
125
+ self.broker.add_info(strat_name, kwargs)
126
+
127
+ def get_info(self, strat_name:str):
128
+ '''Get the info dictionary for the given strategy name from the broker
129
+ '''
130
+ return self.broker.get_info(strat_name)
131
+
121
132
  def qbuffer(self, savemem=0, replaying=False):
122
133
  '''Enable the memory saving schemes. Possible values for ``savemem``:
123
134
 
@@ -22,6 +22,6 @@ from __future__ import (absolute_import, division, print_function,
22
22
  unicode_literals)
23
23
 
24
24
 
25
- __version__ = '2.3.1'
25
+ __version__ = '2.3.2'
26
26
 
27
27
  __btversion__ = tuple(int(x) for x in __version__.split('.'))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: backtrader_next
3
- Version: 2.3.1
3
+ Version: 2.3.3
4
4
  Summary: Live Trading and backtesting platform in Python
5
5
  Project-URL: Homepage, https://github.com/smalinin/backtrader_next
6
6
  Project-URL: Source, https://github.com/smalinin/backtrader_next
@@ -12,7 +12,7 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (G
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Programming Language :: Python :: 3
14
14
  Requires-Python: >=3.11
15
- Requires-Dist: bn-lightweight-charts>=1.1.0
15
+ Requires-Dist: bn-lightweight-charts>=1.2.0
16
16
  Requires-Dist: numba>=0.61.2
17
17
  Requires-Dist: numpy<2.3,>=2.0
18
18
  Requires-Dist: pandas>=2.2.3
@@ -1,6 +1,6 @@
1
1
  backtrader_next/__init__.py,sha256=ktu045IfB6ie3yGyGm9OewtoTth4n2ms00T31BZv-dQ,2615
2
2
  backtrader_next/analyzer.py,sha256=nRP0JiSpnsdbtkvzRVJ7XvS5SzN2hA79vkQGPKlwNrc,14455
3
- backtrader_next/broker.py,sha256=8Aios0brvSAX-6CpzUzvBQeiZYpXKVHLVY1IPpO1IDw,5523
3
+ backtrader_next/broker.py,sha256=6VH2rlVDIsOULkrlrdWYBKoAsI7_5jTr63MjnABDZDE,5840
4
4
  backtrader_next/cerebro.py,sha256=6cn_sgYWIeMIo1VHdpikFzPk39FCCY2G8EUaIMrHV7Q,61169
5
5
  backtrader_next/comminfo.py,sha256=uOO_uWzCctztbB4Ylnp3evJQfy_t88yHYbHfoLCJTKc,11696
6
6
  backtrader_next/dataseries.py,sha256=QG4aho-DdU6nh_CWmz-jrCZ6KS468WWlWpXxfVWTdsg,6737
@@ -17,24 +17,24 @@ backtrader_next/lineseries.py,sha256=-aNlK6FiOm47-cfyH3oIUDI3awsyEmbyAyAg_o-rETA
17
17
  backtrader_next/mathsupport.py,sha256=jc2fTjaf3dWzQ4ZV-ypvVPrHnKnoJbrWLHd-pIhdQ2w,1923
18
18
  backtrader_next/metabase.py,sha256=1g18zfwPOQQlL0MVEYI2pQ-W-FQvfJpG071a_Xbn-N4,11136
19
19
  backtrader_next/observer.py,sha256=xlR7JCYgEcZuwpgLbORPVccRD6cA5RhlkXAfKjVQjdY,2255
20
- backtrader_next/order.py,sha256=mGQ2Yn4OpaE4Ymo6lPHOv9Lz3S70NpCmK3Mo_Hsb6ak,26880
20
+ backtrader_next/order.py,sha256=ayu-AtsG_mJ7tmeOM_K0XguPx0ofH6UAiibYDc96FGE,26931
21
21
  backtrader_next/position.py,sha256=odBPNNkWVRHZnNY03SqP0TSlhP1I8xoCMHJCuS2rH7E,7445
22
22
  backtrader_next/resamplerfilter.py,sha256=z0hqTqbj4nj7gWQPR9qtBk9Iqz8wcqgF3iqL04cMJdA,26141
23
23
  backtrader_next/signal.py,sha256=WwhQUu9L35209K3NEv343dvd57-gBGow1yN9VbmvqPM,1899
24
24
  backtrader_next/sizer.py,sha256=7uf6kzcoD5ko4Rjo9L95e33rq8Dl8t5FE2Rd4FOQxF4,2977
25
25
  backtrader_next/store.py,sha256=3OwuHlgE8VlVrwTIPQPM4_B04pDY6O5fBeu34L52YBo,3145
26
- backtrader_next/strategy.py,sha256=YNrwtYbiwvIwYOraz-tbslFMXkdSh9CZZ1D5WzqQP2I,63415
26
+ backtrader_next/strategy.py,sha256=QXWUDbI1EUfcr8FxoSFwVrSQnEUPQ-_5D7LSNGB2bSo,63827
27
27
  backtrader_next/talib.py,sha256=Q9t2V-jgp-7I9vvPg2BuCJi73GOa7B2LfMrAygPi2nc,9100
28
28
  backtrader_next/timer.py,sha256=WrY5dpyXpGUOEeOtr_3pjiOldQyiUcXQTBpl8Jd2QCY,7578
29
29
  backtrader_next/trade.py,sha256=3AABrbLCxsMubZfenHyONKDCY6j3e-d7bk0ejQPvD8g,11633
30
30
  backtrader_next/tradingcal.py,sha256=X4VQ0dojoKgWoOVTd8aYTyvZYiFZV1TALrQ9sWzb9Rg,9903
31
- backtrader_next/version.py,sha256=u1_y0pDoLEvAuRTjBCj9LuAcBHHn2iek92lwRld93LY,1105
31
+ backtrader_next/version.py,sha256=gITrCqsHGkcPUDfqht4uLG9r96LgAjNl8yOL4qWfbrk,1105
32
32
  backtrader_next/writer.py,sha256=eDyz3xRsDp1i8WIZrXou6MZ80QHpYBzkf_DAqPGOcAw,7712
33
33
  backtrader_next/analyzers/__init__.py,sha256=krHAQhnqyHj0MKGyTIDNqXqqVUTX7dnQeAB1eRwcD9I,1568
34
34
  backtrader_next/analyzers/annualreturn.py,sha256=iIuQAE0nacVEPMyc1JUqIsfkWOG_8kwW104FlXvYd0s,2784
35
35
  backtrader_next/analyzers/calmar.py,sha256=eyfIxodGigJ_BgAhDKC8R9SctGsdUMK9K0WagFVviTM,3826
36
36
  backtrader_next/analyzers/drawdown.py,sha256=cHE5_SMuxYQN7WXDQ9SOyEWZcXRWUV_1QJuqHUcKV1w,6523
37
- backtrader_next/analyzers/eq.py,sha256=SKd-0jNiBXTnelocjewaH-bGoe5WfG-OWYrH4fiSiho,15245
37
+ backtrader_next/analyzers/eq.py,sha256=DS5_Lm8sYO5rI7EV5EJo5u7xWrKfqCky5YoJ8UVd7-0,15254
38
38
  backtrader_next/analyzers/leverage.py,sha256=XjEp6AvSJuALYyIFCLX9U1nZohJ9KmOQmHTxIT4myLY,2402
39
39
  backtrader_next/analyzers/logreturnsrolling.py,sha256=DJimm1ywT2moXVgu27zB-hOrtyA5s1hkQ_et5PYlCwU,5025
40
40
  backtrader_next/analyzers/periodstats.py,sha256=-i1_wTtsLn-pBNDBpYQSdyx-2zxFmsGhaczTSgW9N0g,3570
@@ -201,7 +201,7 @@ backtrader_next/utils/dateintern.py,sha256=VcFWhMw_NazuVMHSvSueNgMxRqiEgu5YmRnz5
201
201
  backtrader_next/utils/flushfile.py,sha256=ekrNdFCs0j4HwRRxho-Fnl0XZBCrpd0uHyq02kV2wjE,1588
202
202
  backtrader_next/utils/ordereddefaultdict.py,sha256=8y7FDnqI1mTcr1NwVfgqsaK-42XwC76Mu_iYRVvLmLM,2091
203
203
  backtrader_next/utils/py3.py,sha256=hSoodWo9-eUXzUCcLoQWPtTR51QxD-m01QzZNcuK9A8,2416
204
- backtrader_next-2.3.1.dist-info/METADATA,sha256=cbrvn_4eEVy5zlF_b3cePM7Si7e4M7tWxJ5LOiwG7zY,11359
205
- backtrader_next-2.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
206
- backtrader_next-2.3.1.dist-info/licenses/LICENSE,sha256=4cCtcomD2KVzNeUs8QZPGv_R1FQXPYzr0-2LSnK0hwQ,35121
207
- backtrader_next-2.3.1.dist-info/RECORD,,
204
+ backtrader_next-2.3.3.dist-info/METADATA,sha256=BySivorjZRIIJRH0AFtLHdj1cgZ4meI-Zvjb0f1MZug,11359
205
+ backtrader_next-2.3.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
206
+ backtrader_next-2.3.3.dist-info/licenses/LICENSE,sha256=4cCtcomD2KVzNeUs8QZPGv_R1FQXPYzr0-2LSnK0hwQ,35121
207
+ backtrader_next-2.3.3.dist-info/RECORD,,