Replies: 6 comments 9 replies
-
Hi @j0el and welcome to the community. I’m not going to be near my computer for the rest of the week, so I cannot post a detailed code example here. But I’ll be able to do so after the Saturday. Can you elaborate more on how you select the top three stocks each month, and what do you mean by random starting points? |
Beta Was this translation helpful? Give feedback.
-
Thanks so much. I found 250 stocks that have been on S&P 500 for many
years (surviver bias free). I want to see if i randomly select 30 (would
play around with this) and buy them one month, then the next month sell
them and buy another 30... For a year. Will they have better returns,
more favorable drawdowns, better sharp than SPY.
I would like to do that starting from different points in time.
My theory is that random selection can beat SPY.
It is a learning exercise for me.
My real strategy is a momentum strategy.
Thanks for any help or suggestions. I would be happy to write it up when
done if that would be helpful to other beginners.
I know two financial advisors who have incredibly complex excel
spreadsheets. When i showed them the examples in your repo and the speed
that they ran, they were really impressed. But beyond excel they have no
programming. I did set them up on colab with some simple examples but
would like to introduce them to your work if I get more familiar with it.
Best regards
…On Mon, Sep 13, 2021, 12:29 PM Oleg Polakow ***@***.***> wrote:
Hi @j0el <https://github.com/j0el> and welcome to the community.
I’m not going to be near my computer for the rest of the week, so I cannot
post a detailed code example here. But I’ll be able to do so after the
Saturday. Can you elaborate more on how you select the top three stocks
each month, and what do you mean by random starting points?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#237 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHWZIRUHYP326NV44SWWRTUBZGK3ANCNFSM5D6OY3VQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
Beta Was this translation helpful? Give feedback.
-
@j0el if you’re curious to attempt this on your own, here is what you need to do:
Feel free to ask any follow-up questions. And sorry if it requires so many steps, I will simplify portfolio optimization with time. But at least you will learn the low-level API with all its flexibility to your advantage. |
Beta Was this translation helpful? Give feedback.
-
Thanks, this is very helpful.
…On Wed, Sep 15, 2021 at 1:13 AM Oleg Polakow ***@***.***> wrote:
@j0el <https://github.com/j0el> if you’re curious to attempt this on your
own, here is what you need to do:
- Build a DataFrame with stock prices, it must contain all stocks for
all years
- Apply
https://vectorbt.dev/docs/generic/accessors.html#vectorbt.generic.accessors.GenericAccessor.rolling_split
with window_len=365 to roll a one year long window over your data. This
will generate many columns, each with 365 data points and starting at a
different date. Notice that index won’t be datetime-like after this
operation (which is fine). Alternatively, you can use
https://vectorbt.dev/docs/generic/splitters.html#vectorbt.generic.splitters.RangeSplitter.split
together with
https://vectorbt.dev/docs/generic/splitters.html#vectorbt.generic.splitters.RangeSplitter
if you know which ranges you want to split into. Just make sure that this
operation produces a single dataframe, not a couple of them (other are
usually meant for test and validation). By looking at your columns, you
will notice that there is a new columns level that tell you the index of
the split. The seclnd object returned by splitting is a lost of indexes
corresponding to each split. Each split depicts basically all your assets
within a year, sharing the same capital, and will form a single backtest.
- Create functions for Portfolio.from_order_func that let you do stock
selection and rebalancing each month. See “ Search and rebalance every 30
days” example in
https://nbviewer.jupyter.org/github/polakowo/vectorbt/blob/master/examples/PortfolioOptimization.ipynb.
Since you want to trade only a selection of stocks, you need to create a
weight vector that has non-zero values for the selected stocks and zero for
all other. Remember to do this per segment. Note that the example in the
notebook rebalances each 30 days - if you want to rebalance at the
beginning of each month, use pandas to get this mask (see
https://pandas.pydata.org/docs/reference/api/pandas.Series.dt.is_month_start.html
)
- Run Portfolio.from_order_func with group_by set to ‘split_idx’ and
cash_sharing to True, such that all assets within a split form a segment
and share the same capital.
Feel free to ask any follow-up questions.
And sorry if it requires so many steps, I will simplify portfolio
optimization with time.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#237 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHWZIQIXRTUORYMXNIZ5B3UCBIRFANCNFSM5D6OY3VQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
Beta Was this translation helpful? Give feedback.
-
Awesome, OP! I am working on understanding your code. I tried to run it,
but get a type error with numba. Since it ran for you I expect it is a
version issue.
Could you please send me a pip or conda list? And how you import numba?
Thanks
/joel
…On Tue, Sep 21, 2021 at 3:54 PM Oleg Polakow ***@***.***> wrote:
Hi @j0el <https://github.com/j0el>,
here's an example I promised you earlier. It selects 2 random stocks out
of 5 every 30 days:
import numpy as npimport pandas as pdimport vectorbt as vbtfrom vectorbt.portfolio import nb
# Load datasymbols = ["GOOG", "AAPL", "FB", "MSFT", "NVDA"]close = vbt.YFData.download(symbols, missing_index='drop').get('Close')
# Select 10 ranges from data, each one year longsplit_close, split_idxs = close.vbt.rolling_split(window_len=365, n=10)
@njitdef fill_size_nb(c):
"""This is your custom function to select stocks and fill the size array."""
# Here we select 2 stocks out of 5 randomly, distribute all cash among them, and set all other to 0
size = np.full(c.group_len, 0, dtype=np.float_)
selected_indices = np.random.choice(c.group_len, 2, replace=False)
size[selected_indices] = 1/2
return size
@njitdef pre_segment_func_nb(c, price):
"""Perform rebalancing at a timestamp."""
for col in range(c.from_col, c.to_col):
# Target percentage requires knowing the value of all assets in the group
# Let's calculate this value using the current order price (remove this to use previous close)
c.last_val_price[col] = nb.get_col_elem_nb(c, col, price)
# Fill the size array
size = fill_size_nb(c)
# Sort by order value to first sell the current positions to release funds
order_value_out = np.empty(c.group_len, dtype=np.float_)
nb.sort_call_seq_nb(c, size, SizeType.TargetPercent, Direction.LongOnly, order_value_out)
# Forward size to order_func_nb
return (size,)
@njitdef order_func_nb(c, size, price, fees):
"""Create an order. Gets only executed if the current segment is active."""
return nb.order_nb(
size=nb.get_elem_nb(c, size),
price=nb.get_elem_nb(c, price),
size_type=SizeType.TargetPercent,
direction=Direction.LongOnly,
fees=nb.get_elem_nb(c, fees)
)
# Use the current close as order priceprice = split_close
# Define rebalancing dates (= active segments)segment_mask = pd.Series(False, index=split_close.index)segment_mask.iloc[::30] = True # every 30 days# You can also create segment_mask as a DataFrame to define a different mask for a different split
# Define and run the simulationpf = vbt.Portfolio.from_order_func(
split_close,
order_func_nb,
vbt.Rep('price'), # *args passed to order_func_nb
vbt.Rep('fees'), # *args passed to order_func_nb
pre_segment_func_nb=pre_segment_func_nb,
pre_segment_args=(
vbt.Rep('price'),
),
broadcast_named_args=dict( # broadcast to a single shape
price=price,
fees=0.001
),
segment_mask=segment_mask,
cash_sharing=True, # share cash within each split
group_by='split_idx' # column level in split_close to split by
)
# Get total return of each splitpf.total_return()split_idx0 1.2182061 0.2733002 0.2013213 -0.0551714 0.1180445 0.0000006 0.0000007 0.2512488 0.0000009 1.071747Name: total_return, dtype: float64
# Plot position value of each stock in the first splitpf[0].asset_value(group_by=False).vbt.plot()
[image: download-63]
<https://user-images.githubusercontent.com/2664108/134257743-2bc72d9e-7d20-4995-9e9c-72e9d1eb62cd.png>
As you see, at most 2 stocks are in the market each month.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#237 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHWZIWREQ2YDTYTHN3BZDLUDEEMDANCNFSM5D6OY3VQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
Beta Was this translation helpful? Give feedback.
-
this is a great thread for noobs. |
Beta Was this translation helpful? Give feedback.
-
First, I am a 75 year old retired guy who is trying to learn how to backtest various strategies. I have completed some Python courses and I know a bit about the market, but am having trouble getting started. I did go over the examples and I can run them, but cannot create a simple one of my own. I was able to do it with an event type backtester, but the vector stuff is confusing to me. And if this is asking too much, just forget it. I will keep trying.
I would like to pick 3 stocks from a set of say GOOG, AAPL, FB, MSFT, NVDA at the beginning of a month and sell them at the end of a month and do that for a year. I woould like to test that against a thousand random starting points. Actually I will choose 30 from a set of 250 survivors, but a simple example would help a lot.
Again, if this is too much of an ask, forgive me.
Beta Was this translation helpful? Give feedback.
All reactions