Skip to content

Commit ab40cf5

Browse files
committed
ENH: Add lib.FractionalBacktest for fractional trading
Implementation according to #134 BTCUSD historical data summarized from: https://www.kaggle.com/datasets/mczielinski/bitcoin-historical-data Thanks @mczielinski/kaggle-bitcoin
1 parent 1dfe96b commit ab40cf5

File tree

5 files changed

+198
-4
lines changed

5 files changed

+198
-4
lines changed

backtesting/__init__.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,19 @@
2626
urlpath=lab%2Ftree%2Fdoc%2Fexamples%2FQuick%20Start%20User%20Guide.ipynb
2727
[colab]: https://colab.research.google.com/github/kernc/backtesting.py/
2828
29+
## Video Tutorials
30+
31+
* Some [**coverage on YouTube**](https://github.com/kernc/backtesting.py/discussions/677).
32+
* [YouTube search](https://www.youtube.com/?q=%22backtesting.py%22)
33+
2934
## Example Strategies
3035
3136
* (contributions welcome)
3237
3338
3439
.. tip::
3540
For an overview of recent changes, see
36-
[What's New](https://github.com/kernc/backtesting.py/blob/master/CHANGELOG.md).
41+
[What's New, i.e. the **Change Log**](https://github.com/kernc/backtesting.py/blob/master/CHANGELOG.md).
3742
3843
3944
## FAQ

backtesting/lib.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from ._plotting import plot_heatmaps as _plot_heatmaps
2626
from ._stats import compute_stats as _compute_stats
2727
from ._util import _Array, _as_str
28-
from .backtesting import Strategy
28+
from .backtesting import Backtest, Strategy
2929

3030
__pdoc__ = {}
3131

@@ -489,6 +489,30 @@ def next(self):
489489
self.data.Close[index] + self.__atr[index] * self.__n_atr)
490490

491491

492+
class FractionalBacktest(Backtest):
493+
"""
494+
A `backtesting.Backtest` that supports fractional share trading
495+
by simple composition. It applies roughly the transformation:
496+
497+
df = (df / satoshi).assign(Volume=df.Volume * satoshi)
498+
499+
as unchallenged in [this FAQ entry on GitHub](https://github.com/kernc/backtesting.py/issues/134),
500+
then passes `data`, `args*`, and `**kwargs` to its super.
501+
502+
Parameter `satoshi` tells the amount of scaling to do. E.g. for
503+
μBTC trading, pass `satoshi=1e6`.
504+
"""
505+
def __init__(self,
506+
data,
507+
*args,
508+
satoshi=int(100e6),
509+
**kwargs):
510+
data = data.copy()
511+
data[['Open', 'High', 'Low', 'Close']] /= satoshi
512+
data['Volume'] *= satoshi
513+
super().__init__(data, *args, **kwargs)
514+
515+
492516
# Prevent pdoc3 documenting __init__ signature of Strategy subclasses
493517
for cls in list(globals().values()):
494518
if isinstance(cls, type) and issubclass(cls, Strategy):

backtesting/test/BTCUSD.csv

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
,Open,High,Low,Close,Volume
2+
2012-01-31,4.58,7.38,3.8,5.55,2012.25343589
3+
2012-02-29,5.55,6.5,3.8,4.99,4761.6090813
4+
2012-03-31,4.99,5.44,4.54,4.92,9049.62628191
5+
2012-04-30,4.92,5.43,4.69,5.0,16484.16777244
6+
2012-05-31,5.0,5.15,4.86,5.14,18520.10380101
7+
2012-06-30,5.14,6.69,5.1,6.54,63694.81610669
8+
2012-07-31,6.54,9.28,6.36,9.2,50656.18175026
9+
2012-08-31,9.2,16.41,7.1,9.81,82848.67116895
10+
2012-09-30,9.81,12.66,9.49,12.17,56093.62696716
11+
2012-10-31,12.17,12.99,9.5,10.75,83104.04747408
12+
2012-11-30,10.75,12.74,10.25,12.42,88709.95682488
13+
2012-12-31,12.42,13.94,12.24,13.24,91377.2908879
14+
2013-01-31,13.24,21.0,12.77,20.79,124484.80488994
15+
2013-02-28,20.79,34.24,19.5,33.98,123510.87774069
16+
2013-03-31,33.98,97.0,32.96,94.08,178272.83745384
17+
2013-04-30,94.08,259.34,45.0,136.84,437933.47186852
18+
2013-05-31,136.83,141.28,81.5,127.24,300589.36039921
19+
2013-06-30,127.24,128.86,86.2,89.0,250031.2382886
20+
2013-07-31,89.01,101.0,63.0,99.67,419753.86745611
21+
2013-08-31,98.72,132.8,90.0,131.24,328441.27534982
22+
2013-09-30,131.24,134.95,115.0,126.24,322672.50941772
23+
2013-10-31,126.24,206.6,85.0,203.74,625096.57168529
24+
2013-11-30,203.7,1163.0,200.23,1110.09,965802.16510373
25+
2013-12-31,1110.09,1153.27,382.21,734.33,953353.15686456
26+
2014-01-31,734.33,995.0,725.0,801.46,444928.559971
27+
2014-02-28,801.46,827.38,400.0,575.5,817663.79165669
28+
2014-03-31,575.5,710.0,436.0,454.0,499158.1329599
29+
2014-04-30,454.0,548.0,339.79,447.56,517371.75097255
30+
2014-05-31,445.23,629.4,420.27,622.0,302311.93173703
31+
2014-06-30,621.01,683.26,538.38,643.41,288960.8787793
32+
2014-07-31,643.5,658.88,555.9,588.5,161612.26069054
33+
2014-08-31,588.98,607.2,442.0,477.78,314687.67223104
34+
2014-09-30,477.75,497.0,365.2,392.64,343002.80183706
35+
2014-10-31,392.83,417.99,275.0,341.82,599895.44176646
36+
2014-11-30,341.82,453.92,316.61,376.43,439599.74922191
37+
2014-12-31,376.43,383.0,304.99,316.67,294441.85716544
38+
2015-01-31,316.67,321.0,152.4,230.59,780354.02856165
39+
2015-02-28,230.58,267.92,208.48,252.0,351708.96955626
40+
2015-03-31,252.0,297.95,236.4,242.92,297384.58919865
41+
2015-04-30,242.92,262.98,210.0,236.76,254714.59684772
42+
2015-05-31,236.69,247.01,227.01,231.52,201312.29784566
43+
2015-06-30,231.5,268.0,219.03,261.78,232269.97896899
44+
2015-07-31,261.7,317.99,252.4,286.11,397787.41249925003
45+
2015-08-31,286.11,286.11,198.12,231.57,418565.66541576
46+
2015-09-30,231.34,246.24,223.0,237.33,569485.98275971
47+
2015-10-31,237.33,334.67,235.0,311.64,713856.53717602
48+
2015-11-30,311.62,502.0,294.0,374.19,886628.21617438
49+
2015-12-31,374.19,467.8,348.64,431.28,422649.12320094
50+
2016-01-31,430.91,465.0,352.0,375.98,288372.04635443003
51+
2016-02-29,375.19,447.99,364.7,435.9,216664.02664585
52+
2016-03-31,435.9,437.5,382.0,416.43,157235.30346074
53+
2016-04-30,416.52,470.02,412.0,449.02,121815.55977623
54+
2016-05-31,449.46,548.5,435.0,522.72,135188.60074123
55+
2016-06-30,522.72,778.85,518.0,664.01,287296.10902287
56+
2016-07-31,662.6,704.99,605.5,631.09,118452.46361069
57+
2016-08-31,632.15,632.35,465.28,571.78,147939.20461568
58+
2016-09-30,571.78,628.99,566.86,604.84,91672.30316333
59+
2016-10-31,604.84,717.99,604.27,704.89,100913.96726614
60+
2016-11-30,704.89,755.07,670.32,741.55,154162.8690078
61+
2016-12-31,741.38,980.74,740.18,963.16,172770.27429349
62+
2017-01-31,963.16,1139.89,751.34,955.79,334633.61649253
63+
2017-02-28,956.67,1220.0,913.73,1195.39,209911.79775014
64+
2017-03-31,1198.65,1350.0,891.33,1069.99,321058.71480166
65+
2017-04-30,1068.4,1347.02,1060.0,1334.83,163259.72058026
66+
2017-05-31,1334.83,2760.1,1330.0,2304.63,463554.71382256
67+
2017-06-30,2304.62,2980.0,2120.0,2519.89,447784.98744192
68+
2017-07-31,2517.0,2938.0,1830.0,2837.44,442045.6083084
69+
2017-08-31,2837.44,4765.21,2615.0,4719.85,376644.9184963
70+
2017-09-30,4724.3,4979.9,2972.01,4318.07,517752.76661262
71+
2017-10-31,4318.07,6420.0,4137.96,6343.37,372951.07664284
72+
2017-11-30,6343.37,11395.0,5555.55,9639.17,483242.2094437
73+
2017-12-31,9639.17,19666.0,9370.11,13808.19,565118.43385979
74+
2018-01-31,13840.53,17234.99,9222.0,9974.52,464529.1276022
75+
2018-02-28,9974.91,11780.0,5920.72,10483.3,579199.79782788
76+
2018-03-31,10482.78,11688.0,6550.0,7058.0,478106.34717399
77+
2018-04-30,7045.11,9755.53,6427.16,9326.6,383170.01395792
78+
2018-05-31,9323.8,9948.98,7026.9,7539.49,315425.59588242
79+
2018-06-30,7530.97,7790.69,5774.72,6325.68,245559.6538061
80+
2018-07-31,6325.67,8496.96,6072.0,7751.32,241646.43315209
81+
2018-08-31,7751.96,7777.0,5880.0,7041.0,241399.24730462
82+
2018-09-30,7041.0,7411.85,6094.38,6575.99,161654.90973714
83+
2018-10-31,6575.0,6756.0,6055.28,6305.0,118357.07729593
84+
2018-11-30,6305.0,6544.0,3474.73,3970.2,342901.30674616
85+
2018-12-31,3970.19,4265.0,3122.28,3750.76,360073.74259956
86+
2019-01-31,3750.62,4112.0,3322.19,3400.32,206637.0603685
87+
2019-02-28,3402.71,4190.0,3328.7,3815.17,203491.41348045
88+
2019-03-31,3814.63,4130.36,3670.0,4095.43,164360.1407343
89+
2019-04-30,4096.77,5627.0,4052.56,5234.42,294712.72910007
90+
2019-05-31,5234.42,9096.79,5224.25,8439.24,369760.90186756
91+
2019-06-30,8443.75,13880.0,7432.84,11231.06,334048.14503083
92+
2019-07-31,11232.4,13200.0,9049.54,9999.82,371432.37053016
93+
2019-08-31,9999.82,12325.0,9320.0,9571.07,249828.48704415
94+
2019-09-30,9584.47,10949.0,7714.7,8279.81,212207.58622774
95+
2019-10-31,8286.24,10350.0,7293.55,9235.75,272266.35117133
96+
2019-11-30,9229.33,9586.5,6515.0,7484.43,187515.893454
97+
2019-12-31,7486.4,7772.71,6425.0,7139.78,129187.45427156
98+
2020-01-31,7145.05,9570.0,6853.53,9289.11,202205.00650995
99+
2020-02-29,9297.2,10500.5,8421.49,8665.35,170803.9857347
100+
2020-03-31,8668.38,9219.13,3850.0,6474.59,481627.36606521
101+
2020-04-30,6472.89,9485.26,6137.71,8847.01,290721.68636726
102+
2020-05-31,8845.12,10074.0,8109.0,9507.95,389152.9589669
103+
2020-06-30,9511.65,10429.26,8830.63,9137.69,210537.6154726
104+
2020-07-31,9130.01,11457.95,8905.0,11333.56,195823.3739246
105+
2020-08-31,11333.15,12473.0,10559.59,11729.64,195276.00613798
106+
2020-09-30,11726.45,12065.82,9825.07,10708.78,211186.60703888
107+
2020-10-31,10703.81,14100.0,10380.0,13794.24,182466.93926815
108+
2020-11-30,13788.52,19864.15,13220.0,19182.23,287212.66517677
109+
2020-12-31,19169.68,29300.0,17569.58,28920.98,255441.8533217
110+
2021-01-31,28912.47,42000.0,27734.0,32487.61,458594.99699076
111+
2021-02-28,32489.13,58354.14,32333.01,43724.75,239530.1816549
112+
2021-03-31,43741.54,61781.83,43500.0,58582.36,158944.2114241
113+
2021-04-30,58601.17,64895.22,47004.2,57098.08,139436.88887224
114+
2021-05-31,57092.42,59603.0,30066.0,36907.65,210064.3136653
115+
2021-06-30,36903.62,41341.57,28600.0,34780.49,143938.56072363
116+
2021-07-31,34786.46,42411.32,29296.39,41335.16,80418.08217585
117+
2021-08-31,41317.48,50562.11,37300.0,47321.52,80413.50047533
118+
2021-09-30,47306.81,52956.47,39573.21,43540.0,70069.98010061
119+
2021-10-31,43545.62,67016.5,43094.68,60730.85,79149.8625657
120+
2021-11-30,60726.59,69000.0,53308.93,58349.19,72105.12010534
121+
2021-12-31,58383.09,59099.64,41967.5,46648.83,71785.05584799
122+
2022-01-31,46659.24,47989.0,32950.72,38479.91,71899.99316572
123+
2022-02-28,38495.66,45850.0,34324.05,41233.87,57380.73682106
124+
2022-03-31,41228.49,48234.0,37169.52,45622.39,58763.17822661
125+
2022-04-30,45617.11,47458.48,37701.0,38487.71,44056.48532558
126+
2022-05-31,38484.87,40050.19,25401.05,31610.61,101260.23960562
127+
2022-06-30,31610.61,31962.79,17592.78,18901.6,106576.31850953
128+
2022-07-31,18892.96,24676.0,18595.6,23837.21,74680.83536261
129+
2022-08-31,23848.21,25212.0,19526.0,20219.0,47733.30210383
130+
2022-09-30,20222.0,22781.0,18157.0,19495.0,69753.68501266
131+
2022-10-31,19486.0,21078.0,18183.0,20368.0,41439.48859683
132+
2022-11-30,20364.0,21473.0,15479.0,16926.0,104475.30523474
133+
2022-12-31,16924.0,18373.0,16293.0,16567.0,56088.35203051
134+
2023-01-31,16567.0,23954.0,16471.0,23171.0,66320.27104302
135+
2023-02-28,23170.0,25270.0,21376.0,23485.0,52595.32439011
136+
2023-03-31,23486.0,29380.0,19569.0,28460.0,91293.2104313
137+
2023-04-30,28462.0,31035.0,26981.0,29383.0,54257.14084866
138+
2023-05-31,29374.0,29851.0,25800.0,27020.0,56558.53819176
139+
2023-06-30,27024.0,31458.0,24756.0,30368.0,71551.9162833
140+
2023-07-31,30364.0,31818.0,28842.0,29157.0,42732.81486405
141+
2023-08-31,29153.0,30210.0,25350.0,26181.0,49687.89486586
142+
2023-09-30,26147.0,27486.0,24920.0,27031.0,41507.07942807
143+
2023-10-31,27031.0,35198.0,26533.0,34553.0,54795.56290504
144+
2023-11-30,34541.0,38457.0,34102.0,37750.0,47345.71140283
145+
2023-12-31,37750.0,44729.0,37619.0,42639.0,52898.75724539
146+
2024-01-31,42652.0,49048.0,38505.0,43500.0,76690.93493603
147+
2024-02-29,43500.0,64000.0,41859.0,60775.0,60701.55689144
148+
2024-03-31,60791.0,73794.0,59313.0,71034.0,91665.33521704
149+
2024-04-30,71088.0,72756.0,59068.0,59150.0,62854.23631911
150+
2024-05-31,59160.0,71958.0,56500.0,67580.0,50415.87703833
151+
2024-06-30,67584.0,71949.0,58456.0,61940.0,47461.77759895
152+
2024-07-31,61931.0,70016.0,53550.0,65243.0,62827.71293164
153+
2024-08-31,65228.0,65568.0,49577.0,58856.0,79937.43578756
154+
2024-09-30,58857.0,65978.0,52546.0,63302.0,39381.43155523
155+
2024-10-31,63331.0,72928.0,58867.0,72346.0,18285.91448949
156+
2024-11-30,69109.0,99121.0,67459.0,97482.0,42421.51031367
157+
2024-12-31,96515.0,108364.0,92092.0,93381.0,25342.80228337

backtesting/test/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def _read_file(filename):
1212
index_col=0, parse_dates=True)
1313

1414

15+
BTCUSD = _read_file('BTCUSD.csv')
16+
"""DataFrame of monthly BTC/USD histrical index data from 2012 through 2024 (12 years)."""
17+
1518
GOOG = _read_file('GOOG.csv')
1619
"""DataFrame of daily NASDAQ:GOOG (Google/Alphabet) stock price data from 2004 to 2013."""
1720

backtesting/test/_test.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from backtesting._stats import compute_drawdown_duration_peaks
2121
from backtesting._util import _Array, _as_str, _Indicator, try_
2222
from backtesting.lib import (
23-
OHLCV_AGG,
23+
FractionalBacktest, OHLCV_AGG,
2424
SignalStrategy,
2525
TrailingStrategy,
2626
barssince,
@@ -32,7 +32,7 @@
3232
random_ohlc_data,
3333
resample_apply,
3434
)
35-
from backtesting.test import EURUSD, GOOG, SMA
35+
from backtesting.test import BTCUSD, EURUSD, GOOG, SMA
3636

3737
SHORT_DATA = GOOG.iloc[:20] # Short data for fast tests with no indicator lag
3838

@@ -937,6 +937,11 @@ def next(self):
937937
stats = Backtest(GOOG, S).run()
938938
self.assertEqual(stats['# Trades'], 56)
939939

940+
def test_FractionalBacktest(self):
941+
ubtc_bt = FractionalBacktest(BTCUSD['2015':], SmaCross, satoshi=1e6, cash=100)
942+
stats = ubtc_bt.run(fast=2, slow=3)
943+
self.assertEqual(stats['# Trades'], 41)
944+
940945

941946
class TestUtil(TestCase):
942947
def test_as_str(self):

0 commit comments

Comments
 (0)