Skip to content

Commit fe17ca8

Browse files
authored
Merge branch 'master' into feature/fix_auto_close
2 parents ecf04d2 + ee324f6 commit fe17ca8

27 files changed

+269
-182
lines changed

.flake8

Lines changed: 0 additions & 6 deletions
This file was deleted.

.github/issue_template.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ python code goes here
2828
<!-- screenshots, code snippets, ... -->
2929

3030
- Backtesting version: 0.?.? <!-- From backtesting.__version__ -->
31+
- `bokeh.__version__`:
32+
- OS:

.github/workflows/ci.yml

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,49 @@ jobs:
88
build:
99
name: Build
1010
runs-on: ubuntu-18.04
11-
1211
strategy:
1312
matrix:
14-
python-version: [3.6, 3.7]
13+
python-version: [3.7, '3.10']
1514
include:
16-
- python-version: 3.8
15+
- python-version: 3.9
1716
test-type: lint
18-
- python-version: 3.8
17+
- python-version: 3.9
1918
test-type: docs
2019

2120
steps:
22-
- name: Set up Python ${{ matrix.python-version }}
23-
uses: actions/setup-python@v2
21+
- uses: actions/setup-python@v4
2422
with:
2523
python-version: ${{ matrix.python-version }}
26-
27-
- uses: actions/cache@v2
28-
name: Set up caches
24+
- uses: actions/cache@v3
2925
with:
3026
path: ~/.cache/pip
3127
key: ${{ runner.os }}-py${{ matrix.python-version }}
32-
33-
- name: Checkout repo
34-
uses: actions/checkout@v2
28+
- uses: actions/checkout@v3
3529
with:
3630
fetch-depth: 3
3731
- name: Fetch tags
3832
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
3933

40-
- name: Install dependencies
41-
run: |
42-
pip install -U pip setuptools wheel
43-
pip install -U --pre .[test]
44-
45-
- name: Install lint dependencies
46-
if: matrix.test-type == 'lint'
47-
run: pip install -U .[dev]
48-
49-
- name: Install docs dependencies
50-
if: matrix.test-type == 'docs'
51-
run: pip install -e .[doc,test] # -e provides _version.py for pdoc
52-
53-
- name: Test w/ Coverage, Lint
54-
if: matrix.test-type == 'lint'
34+
- run: pip install -U pip setuptools wheel
35+
- if: matrix.test-type == 'lint'
36+
run: pip install -U --pre bokeh pandas 'numpy<1.24' && pip install -U .[dev]
37+
- if: matrix.test-type == 'docs'
38+
run: pip install -e .[doc] # -e provides _version.py for pdoc
39+
- run: pip install -U .[test]
40+
41+
- if: matrix.test-type == 'lint'
42+
run: ruff backtesting
43+
- if: matrix.test-type == 'lint'
44+
run: mypy backtesting
45+
- if: matrix.test-type == 'lint'
5546
env: { BOKEH_BROWSER: none }
56-
run: |
57-
flake8
58-
mypy backtesting
59-
time catchsegv coverage run -m backtesting.test
60-
bash <(curl -s https://codecov.io/bash)
47+
run: time catchsegv coverage run -m backtesting.test
48+
- if: matrix.test-type == 'lint'
49+
run: bash <(curl -s https://codecov.io/bash)
6150

62-
- name: Test
63-
if: '! matrix.test-type'
51+
- if: '! matrix.test-type'
6452
env: { BOKEH_BROWSER: none }
6553
run: time catchsegv python -m backtesting.test
6654

67-
- name: Test docs
68-
if: matrix.test-type == 'docs'
55+
- if: matrix.test-type == 'docs'
6956
run: time catchsegv doc/build.sh

CHANGELOG.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@ What's New
33

44
These were the major changes contributing to each release:
55

6-
=======
76
### 0.x.x
87

9-
### 0.3.3
108
* new param on "run()" to manage if trades should be close at end, or not. (#273)
119

10+
11+
### 0.3.3
12+
(2021-12-13)
13+
14+
* Fix random generation with recent NumPy.
15+
* Fix Pandas deprecation warnings.
16+
* Replace Bokeh 3.0 deprecations.
17+
18+
1219
### 0.3.2
1320
(2021-08-03)
1421

CONTRIBUTING.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@ have been fixed already.
1010
To have your issue dealt with promptly, it's best to construct a
1111
[minimal working example] that exposes the issue in a clear and
1212
reproducible manner. Make sure to understand
13-
[how to report bugs effectively][bugs].
13+
[how to report bugs effectively][bugs] and how to
14+
[craft useful bug reports][bugs2] in Python.
1415

15-
Show verbatim code in [fenced code blocks], and use the
16-
preview function!
16+
In case of bugs, please submit full tracebacks
17+
18+
Wrap verbatim example code/traceback in [fenced code blocks],
19+
and use the preview function!
20+
21+
Many thanks from the maintainers!
1722

1823
[minimal working example]: https://en.wikipedia.org/wiki/Minimal_working_example
1924
[bugs]: https://www.chiark.greenend.org.uk/~sgtatham/bugs.html
25+
[bugs2]: https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports
2026
[fenced code blocks]: https://www.markdownguide.org/extended-syntax/#fenced-code-blocks
2127

2228

README.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ Backtesting.py
1010

1111
Backtest trading strategies with Python.
1212

13-
[**Project website**](https://kernc.github.io/backtesting.py)
14-
15-
[Documentation]
16-
17-
[![Star](https://i.imgur.com/LSI6p6O.png)](#top) the project if you use it.
13+
[**Project website**](https://kernc.github.io/backtesting.py) + [Documentation]
1814

1915
[Documentation]: https://kernc.github.io/backtesting.py/doc/backtesting/
2016

@@ -83,6 +79,7 @@ Avg. Trade Duration 32 days 00:00:00
8379
Profit Factor 2.13
8480
Expectancy [%] 6.91
8581
SQN 1.78
82+
Kelly Criterion 0.6134
8683
_strategy SmaCross(n1=10, n2=20)
8784
_equity_curve Equ...
8885
_trades Size EntryB...
@@ -92,6 +89,7 @@ dtype: object
9289

9390
Find more usage examples in the [documentation].
9491

92+
9593
Features
9694
--------
9795
* Simple, well-documented API
@@ -103,6 +101,17 @@ Features
103101
* Detailed results
104102
* Interactive visualizations
105103

104+
![xkcd.com/1570](https://imgs.xkcd.com/comics/engineer_syllogism.png)
105+
106+
107+
Bugs
108+
----
109+
Before reporting bugs or posting to the
110+
[discussion board](https://github.com/kernc/backtesting.py/discussions),
111+
please read [contributing guidelines](CONTRIBUTING.md), particularly the section
112+
about crafting useful bug reports and ```` ``` ````-fencing your code. We thank you!
113+
114+
106115
Alternatives
107116
------------
108117
See [alternatives.md] for a list of alternative Python

backtesting/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
"""
2+
3+
![xkcd.com/1570](https://imgs.xkcd.com/comics/engineer_syllogism.png)
4+
25
## Manuals
36
47
* [**Quick Start User Guide**](../examples/Quick Start User Guide.html)
@@ -12,7 +15,7 @@
1215
1316
These tutorials are also available as live Jupyter notebooks:
1417
[![Binder](https://mybinder.org/badge_logo.svg)][binder]
15-
[![Google Colab](https://colab.research.google.com/assets/colab-badge.svg)][colab]
18+
[![Google Colab](https://colab.research.google.com/assets/colab-badge.png)][colab]
1619
<br>In Colab, you might have to `!pip install backtesting`.
1720
1821
[binder]: \
@@ -50,10 +53,10 @@
5053
# API Reference Documentation
5154
"""
5255
try:
53-
from ._version import version as __version__ # noqa: F401
56+
from ._version import version as __version__
5457
except ImportError:
5558
__version__ = '?.?.?' # Package not installed
5659

57-
from .backtesting import Backtest, Strategy # noqa: F401
5860
from . import lib # noqa: F401
5961
from ._plotting import set_bokeh_output # noqa: F401
62+
from .backtesting import Backtest, Strategy # noqa: F401

backtesting/_plotting.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
tomato as BEAR_COLOR
1717
)
1818
from bokeh.plotting import figure as _figure
19-
from bokeh.models import (
19+
from bokeh.models import ( # type: ignore
2020
CrosshairTool,
2121
CustomJS,
2222
ColumnDataSource,
@@ -25,10 +25,13 @@
2525
HoverTool,
2626
Range1d,
2727
DatetimeTickFormatter,
28-
FuncTickFormatter,
2928
WheelZoomTool,
3029
LinearColorMapper,
3130
)
31+
try:
32+
from bokeh.models import CustomJSTickFormatter
33+
except ImportError: # Bokeh < 3.0
34+
from bokeh.models import FuncTickFormatter as CustomJSTickFormatter # type: ignore
3235
from bokeh.io import output_notebook, output_file, show
3336
from bokeh.io.state import curstate
3437
from bokeh.layouts import gridplot
@@ -85,7 +88,7 @@ def colorgen():
8588
def lightness(color, lightness=.94):
8689
rgb = np.array([color.r, color.g, color.b]) / 255
8790
h, _, s = rgb_to_hls(*rgb)
88-
rgb = np.array(hls_to_rgb(h, lightness, s)) * 255
91+
rgb = np.array(hls_to_rgb(h, lightness, s)) * 255.
8992
return RGB(*rgb)
9093

9194

@@ -138,10 +141,10 @@ def _weighted_returns(s, trades=trades):
138141
return ((df['Size'].abs() * df['ReturnPct']) / df['Size'].abs().sum()).sum()
139142

140143
def _group_trades(column):
141-
def f(s, new_index=df.index.astype(np.int64), bars=trades[column]):
144+
def f(s, new_index=pd.Index(df.index.view(int)), bars=trades[column]):
142145
if s.size:
143146
# Via int64 because on pandas recently broken datetime
144-
mean_time = int(bars.loc[s.index].view('i8').mean())
147+
mean_time = int(bars.loc[s.index].view(int).mean())
145148
new_bar_idx = new_index.get_loc(mean_time, method='nearest')
146149
return new_bar_idx
147150
return f
@@ -209,19 +212,19 @@ def plot(*, results: pd.Series,
209212
new_bokeh_figure = partial(
210213
_figure,
211214
x_axis_type='linear',
212-
plot_width=plot_width,
213-
plot_height=400,
215+
width=plot_width,
216+
height=400,
214217
tools="xpan,xwheel_zoom,box_zoom,undo,redo,reset,save",
215218
active_drag='xpan',
216219
active_scroll='xwheel_zoom')
217220

218221
pad = (index[-1] - index[0]) / 20
219222

220-
fig_ohlc = new_bokeh_figure(
221-
x_range=Range1d(index[0], index[-1],
222-
min_interval=10,
223-
bounds=(index[0] - pad,
224-
index[-1] + pad)) if index.size > 1 else None)
223+
_kwargs = dict(x_range=Range1d(index[0], index[-1],
224+
min_interval=10,
225+
bounds=(index[0] - pad,
226+
index[-1] + pad))) if index.size > 1 else {}
227+
fig_ohlc = new_bokeh_figure(**_kwargs)
225228
figs_above_ohlc, figs_below_ohlc = [], []
226229

227230
source = ColumnDataSource(df)
@@ -242,10 +245,10 @@ def plot(*, results: pd.Series,
242245
trades_cmap = factor_cmap('returns_positive', colors_darker, ['0', '1'])
243246

244247
if is_datetime_index:
245-
fig_ohlc.xaxis.formatter = FuncTickFormatter(
248+
fig_ohlc.xaxis.formatter = CustomJSTickFormatter(
246249
args=dict(axis=fig_ohlc.xaxis[0],
247-
formatter=DatetimeTickFormatter(days=['%d %b', '%a %d'],
248-
months=['%m/%Y', "%b'%y"]),
250+
formatter=DatetimeTickFormatter(days='%a, %d %b',
251+
months='%m/%Y'),
249252
source=source),
250253
code='''
251254
this.labels = this.labels || formatter.doFormat(ticks
@@ -254,7 +257,7 @@ def plot(*, results: pd.Series,
254257
return this.labels[index] || "";
255258
''')
256259

257-
NBSP = '\N{NBSP}' * 4
260+
NBSP = '\N{NBSP}' * 4 # noqa: E999
258261
ohlc_extreme_values = df[['High', 'Low']].copy(deep=False)
259262
ohlc_tooltips = [
260263
('x, y', NBSP.join(('$index',
@@ -266,7 +269,7 @@ def plot(*, results: pd.Series,
266269
('Volume', '@Volume{0,0}')]
267270

268271
def new_indicator_figure(**kwargs):
269-
kwargs.setdefault('plot_height', 90)
272+
kwargs.setdefault('height', 90)
270273
fig = new_bokeh_figure(x_range=fig_ohlc.x_range,
271274
active_scroll='xwheel_zoom',
272275
active_drag='xpan',
@@ -331,7 +334,7 @@ def _plot_equity_section(is_return=False):
331334
source.add(equity, source_key)
332335
fig = new_indicator_figure(
333336
y_axis_label=yaxis_label,
334-
**({} if plot_drawdown else dict(plot_height=110)))
337+
**({} if plot_drawdown else dict(height=110)))
335338

336339
# High-watermark drawdown dents
337340
fig.patch('index', 'equity_dd',
@@ -622,7 +625,7 @@ def __eq__(self, other):
622625
if plot_volume:
623626
custom_js_args.update(volume_range=fig_volume.y_range)
624627

625-
fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args,
628+
fig_ohlc.x_range.js_on_change('end', CustomJS(args=custom_js_args, # type: ignore
626629
code=_AUTOSCALE_JS_CALLBACK))
627630

628631
plots = figs_above_ohlc + [fig_ohlc] + figs_below_ohlc
@@ -647,7 +650,7 @@ def __eq__(self, other):
647650

648651
f.add_tools(linked_crosshair)
649652
wheelzoom_tool = next(wz for wz in f.tools if isinstance(wz, WheelZoomTool))
650-
wheelzoom_tool.maintain_focus = False
653+
wheelzoom_tool.maintain_focus = False # type: ignore
651654

652655
kwargs = {}
653656
if plot_width is None:
@@ -659,7 +662,7 @@ def __eq__(self, other):
659662
toolbar_location='right',
660663
toolbar_options=dict(logo=None),
661664
merge_tools=True,
662-
**kwargs
665+
**kwargs # type: ignore
663666
)
664667
show(fig, browser=None if open_browser else 'none')
665668
return fig
@@ -694,8 +697,8 @@ def plot_heatmaps(heatmap: pd.Series, agg: Union[Callable, str], ncols: int,
694697
y_range=level2,
695698
x_axis_label=name1,
696699
y_axis_label=name2,
697-
plot_width=plot_width // ncols,
698-
plot_height=plot_width // ncols,
700+
width=plot_width // ncols,
701+
height=plot_width // ncols,
699702
tools='box_zoom,reset,save',
700703
tooltips=[(name1, '@' + name1),
701704
(name2, '@' + name2),
@@ -716,7 +719,7 @@ def plot_heatmaps(heatmap: pd.Series, agg: Union[Callable, str], ncols: int,
716719
plots.append(fig)
717720

718721
fig = gridplot(
719-
plots,
722+
plots, # type: ignore
720723
ncols=ncols,
721724
toolbar_options=dict(logo=None),
722725
toolbar_location='above',

0 commit comments

Comments
 (0)