edtechre / pybroker

Algorithmic Trading in Python with Machine Learning

Home Page:https://www.pybroker.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rotational Trading not working when using start_of_month

none2003 opened this issue · comments

Hi @edtechre,

I was testing "10. Rotational Trading.ipynb", but this time I want the rebalancing been performed only at the begin of the month, rather than every bar. So I copied "start_of_month" function from "9. Rebalancing Positions.ipynb" and revised function "rotate" like:

def rotate(ctx: ExecContext):
    if start_of_month(ctx.dt): # <--- adding start_of_month here
        if ctx.long_pos():
            if ctx.symbol not in pyb.param('top_symbols'):
                ctx.sell_all_shares()
        else:
            target_size = pyb.param('target_size')
            ctx.buy_shares = ctx.calc_target_shares(target_size)
            ctx.score = ctx.indicator('roc_20')[-1]

I remain rest of notebook like original. Then odd thing happened, after backtesting, "result.orders" shows only AAPL have trading record. And dut to "max_long_positions=2" and "pyb.param('rank_threshold', 5)", I guess only trading one symbol is not right.

result.orders of rebalance every bars:
1 buy NFLX 2018-02-01 184 NaN 267.67 0.0
2 buy AMD 2018-02-01 3639 NaN 13.53 0.0
3 sell AMD 2018-02-05 3639 NaN 11.56 0.0
4 buy AMZN 2018-02-05 627 NaN 69.49 0.0
5 sell AMZN 2018-04-03 627 NaN 69.23 0.0
6 sell NFLX 2018-04-03 184 NaN 284.63 0.0
7 buy INTC 2018-04-03 966 NaN 49.18 0.0
8 buy MSFT 2018-04-03 534 NaN 88.97 0.0
9 sell INTC 2018-04-26 966 NaN 52.67 0.0
10 buy META 2018-04-26 297 NaN 173.54 0.0
...

result.orders of rebalance every month:
1 buy AAPL 2018-02-01 1194 NaN 41.92 0.0
2 sell AAPL 2018-02-02 1194 NaN 40.86 0.0
3 buy AAPL 2018-03-02 1128 NaN 43.59 0.0
4 sell AAPL 2018-05-02 1128 NaN 43.94 0.0
5 buy AAPL 2018-06-04 1042 NaN 48.10 0.0
...

I uploaded my notebook here, please take a look if it's a pyb bug. Much appreciate.

10. Rotational Trading.zip

Hi @none2003,

That is because of the code you copied:

def start_of_month(dt: datetime) -> bool:
    if dt.month != pyb.param('current_month'):
        pyb.param('current_month', dt.month)
        return True
    return False

That will overwrite the current_month param, limiting you to only one symbol per month. It only returns True once per month, and will return False for the other symbols. The original notebook you referenced calls start_of_month in the set_after_exec callback for multiple symbols.