ematvey / pybacktest Goto Github PK
View Code? Open in Web Editor NEWVectorized backtesting framework in Python / pandas, designed to make your backtesting easier — compact, simple and fast
License: MIT License
Vectorized backtesting framework in Python / pandas, designed to make your backtesting easier — compact, simple and fast
License: MIT License
Shouldn't the sharpe ratio calc be
return (d.mean() / d.std()) * (252**0.5)
instead of
return (d.mean() / d.std()) ** (252**0.5)
Hey thank you for this simple backtester I want to do a backtest for a multiple indicator strategy
Eg:
Buy: Short_ SMA > Long_SMA & RSI < 20 & Short_EMA > Long_EMA
Sell: Short_ SMA < Long_SMA & RSI > 80 & Short_EMA < Long_EMA
I have gone through the example code and I have a confusion in here bt = pybacktest.Backtest(locals(), 'ma_cross')
. Instead of using locals()
I want to use my own custom dict. What format as well as values should I use in this dict?
Thank you for your help
you should add the pyquant package to your setup file since it causes an error.
Hey, is it possible to change default position size to percent of equity or set amount of dollars?
Any suggestions for implementing stop loss and profit target exits? I would be willing to write and contribute any changes to the code with some input.
Приветствую. Подскажите как я могу посчитать эквити в процентах?
Как мне кажется лучше бы код что отвечает за эквити переделать в проценты, а то в статистике данные неверные вылезают. Или я ошибаюсь?
Спасибо
I used it before and it worked. now, I am using python 2.7.3, pandas 0.13.1. it gives no result by calling summary(). positions, prices, report, equity, trades are empty. but trade_price is fine.
For the pythonically challenged... could someone please modify the example notebook to use 4 different buy, cover, short,and sell rules and to show the backtest fuction the long way..
pybacktest.Backtest(self, dataobj, name='Unknown', signal_fields=('buy', 'sell', 'short', 'cover'), price_fields=('buyprice', 'sellprice', 'shortprice', 'coverprice'))
with 'dataobj', name, signal_fields', and 'price_filelds'. the 'locals()' function is making it hard for me to figure this out.. thanks in advance.
When running this:
import pybacktest
ohlc = pybacktest.load_from_yahoo('SPY')
Raises error:
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
<ipython-input-14-09359e4057e9> in <module>()
----> 1 ohlc = pybacktest.load_from_yahoo('SPY')
~/.pyenv/versions/3.5.3/envs/acdt/lib/python3.5/site-packages/pybacktest/data.py in load_from_yahoo(ticker, start, adjust_close)
24 for t in ticker})
25
---> 26 data = dr.DataReader(ticker, data_source='yahoo', start=start)
27 r = data['Adj Close'] / data['Close']
28 ohlc_cols = ['Open', 'High', 'Low', 'Close']
~/.pyenv/versions/3.5.3/envs/acdt/lib/python3.5/site-packages/pandas_datareader/data.py in DataReader(name, data_source, start, end, retry_count, pause, session, access_key)
119 adjust_price=False, chunksize=25,
120 retry_count=retry_count, pause=pause,
--> 121 session=session).read()
122
123 elif data_source == "yahoo-actions":
~/.pyenv/versions/3.5.3/envs/acdt/lib/python3.5/site-packages/pandas_datareader/yahoo/daily.py in read(self)
113 """ read one data from specified URL """
114 try:
--> 115 df = super(YahooDailyReader, self).read()
116 if self.ret_index:
117 df['Ret_Index'] = _calc_return_index(df['Adj Close'])
~/.pyenv/versions/3.5.3/envs/acdt/lib/python3.5/site-packages/pandas_datareader/base.py in read(self)
179 if isinstance(self.symbols, (compat.string_types, int)):
180 df = self._read_one_data(self.url,
--> 181 params=self._get_params(self.symbols))
182 # Or multiple symbols, (e.g., ['GOOG', 'AAPL', 'MSFT'])
183 elif isinstance(self.symbols, DataFrame):
~/.pyenv/versions/3.5.3/envs/acdt/lib/python3.5/site-packages/pandas_datareader/yahoo/daily.py in _get_params(self, symbol)
97
98 def _get_params(self, symbol):
---> 99 unix_start = int(time.mktime(self.start.timetuple()))
100 day_end = self.end.replace(hour=23, minute=59, second=59)
101 unix_end = int(time.mktime(day_end.timetuple()))
OverflowError: mktime argument out of range
Hi! First of all great library. I was looking for something like this as I am looking for a backtester for http://docs.kloudtrader.com. It's always better to extend something instead of reinventing the wheel but I don't see any License. So i wanted to seek permission to extend this library! Lemme know if this could be possible.
Thanks!
Hello!
When i wanted install a package
"pip install git+https://github.com/ematvey/pybacktest.git"
I got a error:
Fatal: unable to access 'https://github.com/ematvey/pybacktest.git/': OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443
What am i doing wrong?
Hi, I got a little confused about the difference between positions and pos in trades. I see that there are two shift in pos in trades. Can you tell me why? Thanks very much.
Hi there,
would it be possible to test only buy signals to evaluate buy signals strength/ performances?
I have gone through the example code and I have a confusion in here bt = pybacktest.Backtest(locals(), 'ma_cross'). Instead of using locals() I want to use my own custom dict. What format as well as values should I use in this dict?
Thank you for your help
Thank you for open-sourcing this nice package. I was wondering if there is a plan to release it to pypi, so it would be more accessible. Downloading/installing would take just one command.
When testing with hourly data instead of the daily on the example app (ms/ml) and calling the summary, I get the following error:
Traceback (most recent call last):
File "pyback1.py", line 75, in <module>
print(bt.summary())
File "/usr/local/lib/python3.7/site-packages/pybacktest/backtest.py", line 174, in summary
print((yaml.dump(self.report, allow_unicode=True, default_flow_style=False)))
File "/usr/local/lib/python3.7/site-packages/cached_property.py", line 35, in __get__
value = obj.__dict__[self.func.__name__] = self.func(obj)
File "/usr/local/lib/python3.7/site-packages/pybacktest/backtest.py", line 164, in report
return pybacktest.performance.performance_summary(self.equity)
File "/usr/local/lib/python3.7/site-packages/cached_property.py", line 35, in __get__
value = obj.__dict__[self.func.__name__] = self.func(obj)
File "/usr/local/lib/python3.7/site-packages/pybacktest/backtest.py", line 152, in equity
return pybacktest.parts.trades_to_equity(self.trades)
File "/usr/local/lib/python3.7/site-packages/cached_property.py", line 35, in __get__
value = obj.__dict__[self.func.__name__] = self.func(obj)
File "/usr/local/lib/python3.7/site-packages/pybacktest/backtest.py", line 142, in trades
assert p.index.tz == tp.index.tz, "Cant operate on singals and prices " \
AttributeError: 'Index' object has no attribute 'tz'
The data looks similar, with the date format being more detailed.
I was using pd.to_datetime on a csv (without a timezone information). If there is no TimeZone information it would be nice to have a better error message.
Solution: Add a Timezone, pd.to_datetime(x, utc=True) in my case
I like your whole approach on performing efficients backtest via pandas. But could you provide more documentation regarding your performance statistics and reporting file?
The tutorial mentions figsize.
What module does it belong to?
Hello, I noticed Optimizer class, is it working, or is it unfinished?
I am using Python 3.7 and Pandas 0.24
I get this error from holding_periods function.
def holding_periods(eqd):
# rather crude, but will do
return pd.Series(eqd.index.to_datetime(), index=eqd.index, dtype=object).diff().dropna()
Should it be?
def holding_periods(eqd):
# rather crude, but will do
return pd.Series(pd.to_datetime (eqd.index), index=eqd.index, dtype=object).diff().dropna()
Or it might be deprecated in latest versions of Pandas:
https://pandas.pydata.org/pandas-docs/version/0.21/generated/pandas.Timestamp.to_datetime.html
Timestamp.to_datetime()
DEPRECATED: use to_pydatetime() instead.Convert a Timestamp object to a native Python datetime object.
AttributeError Traceback (most recent call last)
in
----> 1 bt.summary()
C:\ProgramData\Anaconda3\lib\site-packages\pybacktest\backtest.py in summary(self)
172 print(s)
173 print(('-' * len(s) + '\n'))
--> 174 print((yaml.dump(self.report, allow_unicode=True, default_flow_style=False)))
175 print(('-' * len(s)))
176
C:\ProgramData\Anaconda3\lib\site-packages\cached_property.py in get(self, obj, cls)
33 return self._wrap_in_coroutine(obj)
34
---> 35 value = obj.dict[self.func.name] = self.func(obj)
36 return value
37
C:\ProgramData\Anaconda3\lib\site-packages\pybacktest\backtest.py in report(self)
162 @cached_property
163 def report(self):
--> 164 return pybacktest.performance.performance_summary(self.equity)
165
166 def summary(self):
C:\ProgramData\Anaconda3\lib\site-packages\pybacktest\performance.py in performance_summary(equity_diffs, quantile, precision)
89 if len(eqd) == 0:
90 return {}
---> 91 hold = holding_periods(equity_diffs)
92
93 return _format_out({
C:\ProgramData\Anaconda3\lib\site-packages\pybacktest\performance.py in holding_periods(eqd)
68 def holding_periods(eqd):
69 # rather crude, but will do
---> 70 return pd.Series(eqd.index.to_datetime(), index=eqd.index, dtype=object).diff().dropna()
71
72
AttributeError: 'DatetimeIndex' object has no attribute 'to_datetime'
This is an issue with the pictured hello world code (bottom left).
Actually, here is the shortest MWE:
import matplotlib
import matplotlib.pyplot as plt
import pybacktest
import pandas as pd
short_ma = 50
long_ma = 200
ohlc = pybacktest.load_from_yahoo('AAPL', start=2000)
ohlc.tail()
ms = ohlc.C.rolling(short_ma).mean()
ml = ohlc.C.rolling(long_ma).mean()
buy = cover = (ms > ml) & (ms.shift() < ml.shift()) # ma cross up
sell = short = (ms < ml) & (ms.shift() > ml.shift()) # ma cross down
bt = pybacktest.Backtest(locals(), 'ma_cross')
print(bt.summary())
matplotlib.rcParams['figure.figsize'] = (15.0, 8.0)
bt.plot_equity()
Hi there,
To properly adjust your historical OHLC data, you need to use a proportional adjustment. Here's the function that does just that:
def adjust_ohlc(data):
"""
Adjust OHLC prices for splits and dividends by using
the Adjusted column in Yahoo!.
"""
ratio = data['AC']/data['C']
data['UC'] = data['C'] # add an unadjusted close column
data[['O', 'H', 'L', 'C']] *= ratio
return data.drop(['AC'], axis=1)
Note that it does not adjust the Volume.
pls, correct code
+
here and in nearby
pf = PF = lambda eqd: abs(eqd[eqd > 0].sum() / eqd[eqd < 0].sum())
get error when eqd[eqd < 0].sum() == 0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.