Skip to content

Commit

Permalink
Merge pull request #297 from jpmorganchase/pages
Browse files Browse the repository at this point in the history
changes to pages/deploy
  • Loading branch information
timkpaine authored Apr 24, 2021
2 parents 6529016 + 0cc3146 commit 2985ff0
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ docs:

pages:
- rm -rf $(TMPREPO)
git clone -b gh-pages https://github.com/pmorissette/bt.git $(TMPREPO)
git clone -b gh-pages git@github.com:pmorissette/bt.git $(TMPREPO)
rm -rf $(TMPREPO)/*
cp -r docs/build/html/* $(TMPREPO)
cd $(TMPREPO); \
Expand Down
48 changes: 23 additions & 25 deletions docs/source/examples-nb.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


SMA Strategy
------------

Expand All @@ -15,11 +13,11 @@ Given the flexibility of **bt**, there is no strict rule. The average calculatio

Now that we know what we have to do, let's get started. First we will download some data and calculate the simple moving average.

.. code:: python
.. code:: ipython2
import bt
.. code:: python
.. code:: ipython2
# download data
data = bt.get('aapl,msft,c,gs,ge', start='2010-01-01')
Expand All @@ -32,7 +30,7 @@ Now that we know what we have to do, let's get started. First we will download s
It's always a good idea to plot your data to make sure it looks ok. So let's see how the data + sma plot looks like.

.. code:: python
.. code:: ipython2
# let's see what the data looks like - this is by no means a pretty chart, but it does the job
plot = bt.merge(data, sma).plot(figsize=(15, 5))
Expand All @@ -52,9 +50,9 @@ Before we do that, let's think about how we will code it. We could pass the SMA

For example, what if we wanted to select securities that were below their sma? Or what if we only wanted securities that were 5% above their sma?

What we could do instead is pre-calculate the selection logic DataFrame (a fast, vectorized operation) and write a generic Algo that takes in this boolean DataFrame and returns the securities where the value is True on a given date. This will be much faster and much more reusable. Let's see how the implementation looks like.
What we could do instead is pre-calculate the selection logic DataFrame (a fast, vectorized operation) and write a generic Algo that takes in this boolean DataFrame and returns the securities where the value is True on a given date. This will be must faster and much more reusable. Let's see how the implementation looks like.

This comment has been minimized.

Copy link
@jeamick

jeamick Apr 28, 2021

Contributor

Is it "much" right ?

This comment has been minimized.

Copy link
@timkpaine

timkpaine Apr 28, 2021

Author Collaborator

😂yeah this looks wrong

This comment has been minimized.

Copy link
@jeamick

jeamick Apr 28, 2021

Contributor

ahaha np man


.. code:: python
.. code:: ipython2
class SelectWhere(bt.Algo):
Expand Down Expand Up @@ -101,7 +99,7 @@ All we have to do now is pass in a signal matrix. In our case, it's quite easy::

Simple, concise and more importantly, fast! Let's move on and test the strategy.

.. code:: python
.. code:: ipython2
# first we create the Strategy
s = bt.Strategy('above50sma', [SelectWhere(data > sma),
Expand All @@ -125,7 +123,7 @@ Simple, concise and more importantly, fast! Let's move on and test the strategy.
So just to recap, we created the strategy, created the backtest by joining Strategy+Data, and ran the backtest. Let's see the results.

.. code:: python
.. code:: ipython2
# what does the equity curve look like?
res.plot()
Expand All @@ -136,7 +134,7 @@ So just to recap, we created the strategy, created the backtest by joining Strat
:class: pynb


.. code:: python
.. code:: ipython2
# and some performance stats
res.display()
Expand Down Expand Up @@ -208,7 +206,7 @@ Nothing stellar but at least you learnt something along the way (I hope).

Oh, and one more thing. If you were to write your own "library" of backtests, you might want to write yourself a helper function that would allow you to test different parameters and securities. That function might look something like this:

.. code:: python
.. code:: ipython2
def above_sma(tickers, sma_per=50, start='2010-01-01', name='above_sma'):
"""
Expand All @@ -231,7 +229,7 @@ Oh, and one more thing. If you were to write your own "library" of backtests, yo
This function allows us to easily generate backtests. We could easily compare a few different SMA periods. Also, let's see if we can beat a long-only allocation to the SPY.

.. code:: python
.. code:: ipython2
# simple backtest to test long-only allocation
def long_only_ew(tickers, start='2010-01-01', name='long_only_ew'):
Expand Down Expand Up @@ -266,7 +264,7 @@ This function allows us to easily generate backtests. We could easily compare a
0% 100%
[############################# ] | ETA: 00:00:00
.. code:: python
.. code:: ipython2
res2.plot(freq='m')
Expand All @@ -276,7 +274,7 @@ This function allows us to easily generate backtests. We could easily compare a
:class: pynb


.. code:: python
.. code:: ipython2
res2.display()
Expand Down Expand Up @@ -355,7 +353,7 @@ Basically, when the 50 day moving average will be above the 200-day moving avera

Here's the WeighTarget implementation (this Algo also already exists in the algos module):

.. code:: python
.. code:: ipython2
class WeighTarget(bt.Algo):
"""
Expand Down Expand Up @@ -387,7 +385,7 @@ Here's the WeighTarget implementation (this Algo also already exists in the algo
So let's start with a simple 50-200 day sma crossover for a single security.

.. code:: python
.. code:: ipython2
## download some data & calc SMAs
data = bt.get('spy', start='2010-01-01')
Expand All @@ -407,7 +405,7 @@ So let's start with a simple 50-200 day sma crossover for a single security.
Ok so we downloaded our data, calculated the simple moving averages, and then we setup our target weight (tw) DataFrame. Let's take a look at our target weights to see if they make any sense.

.. code:: python
.. code:: ipython2
# plot the target weights + chart of price & SMAs
tmp = bt.merge(tw, data, sma50, sma200)
Expand All @@ -425,7 +423,7 @@ As mentioned earlier, it's always a good idea to plot your strategy data. It is

Now let's move on with the Strategy & Backtest.

.. code:: python
.. code:: ipython2
ma_cross = bt.Strategy('ma_cross', [WeighTarget(tw),
bt.algos.Rebalance()])
Expand All @@ -441,7 +439,7 @@ Now let's move on with the Strategy & Backtest.
0% 100%
[############################# ] | ETA: 00:00:00
.. code:: python
.. code:: ipython2
res.plot()
Expand All @@ -463,7 +461,7 @@ The most straightforward way would be to test the different sub-strategies, extr

Let's see how this looks:

.. code:: python
.. code:: ipython2
# first let's create a helper function to create a ma cross backtest
def ma_cross(ticker, start='2010-01-01',
Expand Down Expand Up @@ -520,7 +518,7 @@ Let's see how this looks:
0% 100%
[############################# ] | ETA: 00:00:00
.. code:: python
.. code:: ipython2
res.plot()
Expand All @@ -530,7 +528,7 @@ Let's see how this looks:
:class: pynb


.. code:: python
.. code:: ipython2
res.plot_weights()
Expand All @@ -549,7 +547,7 @@ This means that the parent strategy can use the price information (which reflect

Perhaps some code will help:

.. code:: python
.. code:: ipython2
# once again, we will create a few backtests
# these will be the child strategies
Expand Down Expand Up @@ -579,7 +577,7 @@ Perhaps some code will help:
0% 100%
[############################# ] | ETA: 00:00:00
.. code:: python
.. code:: ipython2
res.plot()
Expand All @@ -589,7 +587,7 @@ Perhaps some code will help:
:class: pynb


.. code:: python
.. code:: ipython2
res.plot_weights()
Expand Down
21 changes: 10 additions & 11 deletions docs/source/intro.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

.. code:: python
.. code:: ipython2
import bt
Expand All @@ -11,7 +10,7 @@ Let's create a simple strategy. We will create a monthly rebalanced, long-only s

First, we will download some data. By default, :func:`bt.get (alias for ffn.get) <ffn.data.get>` downloads the Adjusted Close from Yahoo! Finance. We will download some data starting on January 1, 2010 for the purposes of this demo.

.. code:: python
.. code:: ipython2
# fetch some data
data = bt.get('spy,agg', start='2010-01-01')
Expand All @@ -33,7 +32,7 @@ First, we will download some data. By default, :func:`bt.get (alias for ffn.get)
Once we have our data, we will create our strategy. The :class:`Strategy <bt.core.Strategy>` object contains the strategy logic by combining various :class:`Algos <bt.core.Algo>`.

.. code:: python
.. code:: ipython2
# create the strategy
s = bt.Strategy('s1', [bt.algos.RunMonthly(),
Expand All @@ -46,7 +45,7 @@ Finally, we will create a :class:`Backtest <bt.backtest.Backtest>`, which is the

Once this is done, we can run the backtest and analyze the results.

.. code:: python
.. code:: ipython2
# create a backtest and run it
test = bt.Backtest(s, data)
Expand All @@ -63,7 +62,7 @@ Once this is done, we can run the backtest and analyze the results.
Now we can analyze the results of our backtest. The :class:`Result <bt.backtest.Result>` object is a thin wrapper around `ffn.GroupStats <http://pmorissette.github.io/ffn/ffn.html#ffn.core.GroupStats>`__ that adds some helper methods.

.. code:: python
.. code:: ipython2
# first let's see an equity curve
res.plot()
Expand All @@ -74,7 +73,7 @@ Now we can analyze the results of our backtest. The :class:`Result <bt.backtest.
:class: pynb


.. code:: python
.. code:: ipython2
# ok and what about some stats?
res.display()
Expand Down Expand Up @@ -141,7 +140,7 @@ Now we can analyze the results of our backtest. The :class:`Result <bt.backtest.
Win 12m % 96.00%
.. code:: python
.. code:: ipython2
# ok and how does the return distribution look like?
res.plot_histogram()
Expand All @@ -152,7 +151,7 @@ Now we can analyze the results of our backtest. The :class:`Result <bt.backtest.
:class: pynb


.. code:: python
.. code:: ipython2
# and just to make sure everything went along as planned, let's plot the security weights over time
res.plot_security_weights()
Expand All @@ -169,7 +168,7 @@ Modifying a Strategy

Now what if we ran this strategy weekly and also used some risk parity style approach by using weights that are proportional to the inverse of each asset's volatility? Well, all we have to do is plug in some different algos. See below:

.. code:: python
.. code:: ipython2
# create our new strategy
s2 = bt.Strategy('s2', [bt.algos.RunWeekly(),
Expand Down Expand Up @@ -197,7 +196,7 @@ Now what if we ran this strategy weekly and also used some risk parity style app
:class: pynb


.. code:: python
.. code:: ipython2
res2.display()
Expand Down

0 comments on commit 2985ff0

Please sign in to comment.