Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open short position right after closing long position with full capital #697

Open
kevin851066 opened this issue Apr 2, 2024 · 3 comments

Comments

@kevin851066
Copy link

First of all, thanks for developing this excellent library!

My strategy will enter short/long position right after closing long/short position, while short/long signal happens. And each postion will entry with full capital

Here is my code:

start = '2019-01-01 UTC'  # crypto is in UTC
end = '2020-01-01 UTC'
btc_price = vbt.YFData.download('BTC-USD', start=start, end=end).get('Close')


fast_ma = vbt.MA.run(btc_price, 10, short_name='fast')
slow_ma = vbt.MA.run(btc_price, 20, short_name='slow')

entries = fast_ma.ma_crossed_above(slow_ma)
exits = fast_ma.ma_crossed_below(slow_ma)

pf = vbt.Portfolio.from_signals(btc_price, 
                                entries=entries, 
                                exits=exits,
                                short_entries=exits,
                                short_exits=entries,
                                size = 1,
                                # size_type='amount',
                                size_type=2,
                                fees=0.001,
                                init_cash=1000)

And I got an error, seems like vectorbt does not support this behavior.

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[37], [line 12](vscode-notebook-cell:?execution_count=37&line=12)
      [9](vscode-notebook-cell:?execution_count=37&line=9) entries = fast_ma.ma_crossed_above(slow_ma)
     [10](vscode-notebook-cell:?execution_count=37&line=10) exits = fast_ma.ma_crossed_below(slow_ma)
---> [12](vscode-notebook-cell:?execution_count=37&line=12) pf = vbt.Portfolio.from_signals(btc_price, 
     [13](vscode-notebook-cell:?execution_count=37&line=13)                                 entries=entries, 
     [14](vscode-notebook-cell:?execution_count=37&line=14)                                 exits=exits,
     [15](vscode-notebook-cell:?execution_count=37&line=15)                                 short_entries=exits,
     [16](vscode-notebook-cell:?execution_count=37&line=16)                                 short_exits=entries,
     [17](vscode-notebook-cell:?execution_count=37&line=17)                                 size = 1,
     [18](vscode-notebook-cell:?execution_count=37&line=18)                                 # size_type='amount',
     [19](vscode-notebook-cell:?execution_count=37&line=19)                                 size_type=2,
     [20](vscode-notebook-cell:?execution_count=37&line=20)                                 fees=0.001,
     [21](vscode-notebook-cell:?execution_count=37&line=21)                                 init_cash=1000)

File [~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2960](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2960), in Portfolio.from_signals(cls, close, entries, exits, short_entries, short_exits, signal_func_nb, signal_args, size, size_type, price, fees, fixed_fees, slippage, min_size, max_size, size_granularity, reject_prob, lock_cash, allow_partial, raise_reject, log, accumulate, upon_long_conflict, upon_short_conflict, upon_dir_conflict, upon_opposite_entry, direction, val_price, open, high, low, sl_stop, sl_trail, tp_stop, stop_entry_price, stop_exit_price, upon_stop_exit, upon_stop_update, adjust_sl_func_nb, adjust_sl_args, adjust_tp_func_nb, adjust_tp_args, use_stops, init_cash, cash_sharing, call_seq, ffill_val_price, update_value, max_orders, max_logs, seed, group_by, broadcast_named_args, broadcast_kwargs, template_mapping, wrapper_kwargs, freq, attach_call_seq, **kwargs)
   [2957](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2957) checks.assert_numba_func(adjust_tp_func_nb)
   [2959](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2959) # Perform the simulation
-> [2960](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2960) order_records, log_records = nb.simulate_from_signal_func_nb(
   [2961](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2961)     target_shape_2d,
   [2962](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2962)     cs_group_lens,  # group only if cash sharing is enabled to speed up
   [2963](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2963)     init_cash,
   [2964](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2964)     call_seq,
   [2965](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2965)     signal_func_nb=signal_func_nb,
   [2966](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2966)     signal_args=signal_args,
   [2967](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2967)     size=broadcasted_args['size'],
   [2968](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2968)     price=broadcasted_args['price'],
   [2969](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2969)     size_type=broadcasted_args['size_type'],
   [2970](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2970)     fees=broadcasted_args['fees'],
   [2971](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2971)     fixed_fees=broadcasted_args['fixed_fees'],
   [2972](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2972)     slippage=broadcasted_args['slippage'],
   [2973](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2973)     min_size=broadcasted_args['min_size'],
   [2974](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2974)     max_size=broadcasted_args['max_size'],
   [2975](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2975)     size_granularity=broadcasted_args['size_granularity'],
   [2976](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2976)     reject_prob=broadcasted_args['reject_prob'],
   [2977](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2977)     lock_cash=broadcasted_args['lock_cash'],
   [2978](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2978)     allow_partial=broadcasted_args['allow_partial'],
   [2979](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2979)     raise_reject=broadcasted_args['raise_reject'],
   [2980](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2980)     log=broadcasted_args['log'],
   [2981](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2981)     accumulate=broadcasted_args['accumulate'],
   [2982](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2982)     upon_long_conflict=broadcasted_args['upon_long_conflict'],
   [2983](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2983)     upon_short_conflict=broadcasted_args['upon_short_conflict'],
   [2984](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2984)     upon_dir_conflict=broadcasted_args['upon_dir_conflict'],
   [2985](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2985)     upon_opposite_entry=broadcasted_args['upon_opposite_entry'],
   [2986](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2986)     val_price=broadcasted_args['val_price'],
   [2987](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2987)     open=broadcasted_args['open'],
   [2988](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2988)     high=broadcasted_args['high'],
   [2989](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2989)     low=broadcasted_args['low'],
   [2990](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2990)     close=broadcasted_args['close'],
   [2991](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2991)     sl_stop=broadcasted_args['sl_stop'],
   [2992](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2992)     sl_trail=broadcasted_args['sl_trail'],
   [2993](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2993)     tp_stop=broadcasted_args['tp_stop'],
   [2994](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2994)     stop_entry_price=broadcasted_args['stop_entry_price'],
   [2995](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2995)     stop_exit_price=broadcasted_args['stop_exit_price'],
   [2996](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2996)     upon_stop_exit=broadcasted_args['upon_stop_exit'],
   [2997](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2997)     upon_stop_update=broadcasted_args['upon_stop_update'],
   [2998](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2998)     adjust_sl_func_nb=adjust_sl_func_nb,
   [2999](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:2999)     adjust_sl_args=adjust_sl_args,
   [3000](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3000)     adjust_tp_func_nb=adjust_tp_func_nb,
   [3001](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3001)     adjust_tp_args=adjust_tp_args,
   [3002](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3002)     use_stops=use_stops,
   [3003](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3003)     auto_call_seq=auto_call_seq,
   [3004](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3004)     ffill_val_price=ffill_val_price,
   [3005](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3005)     update_value=update_value,
   [3006](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3006)     max_orders=max_orders,
   [3007](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3007)     max_logs=max_logs,
   [3008](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3008)     flex_2d=close.ndim == 2
   [3009](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3009) )
   [3011](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3011) # Create an instance
   [3012](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3012) return cls(
   [3013](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3013)     wrapper,
   [3014](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3014)     close,
   (...)
   [3020](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3020)     **kwargs
   [3021](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/base.py:3021) )

File [~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1724](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1724), in signals_to_size_nb()
   [1722](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1722) if not np.isnan(size):
   [1723](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1723)     if size_type == SizeType.Percent:
-> [1724](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1724)         raise ValueError(
   [1725](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1725)             "SizeType.Percent does not support position reversal using signals")
   [1726](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1726)     if size_type == SizeType.Value:
   [1727](https://file+.vscode-resource.vscode-cdn.net/Users/kevin851066/Desktop/JZ/range_filter/~/opt/anaconda3/envs/quant/lib/python3.8/site-packages/vectorbt/portfolio/nb.py:1727)         order_size -= size [/](https://file+.vscode-resource.vscode-cdn.net/) val_price_now

ValueError: SizeType.Percent does not support position reversal using signals

Is there any methods that can implement it?

The first straightforward method came up with my mind is that I can let short_entries = np.roll(exits, 1) to make them not to happen at the same time. But this method will make the backtest result inaccurate since my short_entries lag by one timeframe

Thanks in advance!

@polakowo
Copy link
Owner

polakowo commented Apr 3, 2024

You just need to remove size and size_type, VBT enters with full capital by default.

@polakowo
Copy link
Owner

polakowo commented Apr 3, 2024

And for position reversal, instead of providing short_entries and short_exits you can simply use direction="both".

@kevin851066
Copy link
Author

I see. Thank for your quick reply!

Another question:
I would like to calculate the benchmark's mdd, sharpe ratio. Could it be done by pf.stats()?

My current usage for pf.stats():

stats = pf.stats(metrics=[
            'start',
            'end',
            'total_return',
            'benchmark_return',
            'sharpe_ratio',
            'max_dd',
            'total_trades',
            'win_rate'], agg_func=None)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants