def generate_both(cls, shape, entry_choice_func_nb, exit_choice_func_nb, entry_args, exit_args, **kwargs): """See `vectorbt.signals.nb.generate_enex_nb`. `**kwargs` will be passed to pandas constructor. Example: Generate entry and exit signals one after another: ```python-repl >>> @njit ... def entry_choice_func_nb(col, from_i, to_i, wait1): ... next_pos = col + from_i + wait1 ... if next_pos < to_i: ... return np.array([next_pos]) ... return np.empty(0, dtype=np.int_) >>> @njit ... def exit_choice_func_nb(col, from_i, to_i, wait2): ... next_pos = col + from_i + wait2 ... if next_pos < to_i: ... return np.array([next_pos]) ... return np.empty(0, dtype=np.int_) >>> en, ex = pd.DataFrame.vbt.signals.generate_both( ... (5, 3), entry_choice_func_nb, exit_choice_func_nb, (0,), (1,), ... index=sig.index, columns=sig.columns) >>> en a b c 2020-01-01 True False False 2020-01-02 False True False 2020-01-03 False False True 2020-01-04 True False False 2020-01-05 False False False >>> ex a b c 2020-01-01 False False False 2020-01-02 False False False 2020-01-03 True False False 2020-01-04 False False False 2020-01-05 False True False ```""" checks.assert_numba_func(entry_choice_func_nb) checks.assert_numba_func(exit_choice_func_nb) if not isinstance(shape, tuple): shape = (shape, 1) elif isinstance(shape, tuple) and len(shape) == 1: shape = (shape[0], 1) result1, result2 = nb.generate_enex_nb( shape, entry_choice_func_nb, exit_choice_func_nb, entry_args, exit_args ) if cls.is_series(): if shape[1] > 1: raise ValueError("Use DataFrame accessor") return pd.Series(result1[:, 0], **kwargs), pd.Series(result2[:, 0], **kwargs) return pd.DataFrame(result1, **kwargs), pd.DataFrame(result2, **kwargs)
def apply_nb(i, shape, entry_wait, exit_wait, entry_input_list, exit_input_list, entry_in_output_tuples, exit_in_output_tuples, entry_param_tuples, exit_param_tuples, entry_args, exit_args): return generate_enex_nb( shape, entry_wait, exit_wait, entry_choice_func, (*entry_input_list, *entry_in_output_tuples[i], *entry_param_tuples[i], *entry_args), exit_choice_func, (*exit_input_list, *exit_in_output_tuples[i], *exit_param_tuples[i], *exit_args))
def generate_both(cls, shape, entry_choice_func_nb, exit_choice_func_nb, entry_args=None, exit_args=None, entry_wait=1, exit_wait=1, **kwargs): """See `vectorbt.signals.nb.generate_enex_nb`. `**kwargs` will be passed to pandas constructor. ## Example Generate entry and exit signals one after another. Each column increment the number of ticks to wait before placing the exit signal. ```python-repl >>> @njit ... def entry_choice_func_nb(from_i, to_i, col, temp_idx_arr): ... temp_idx_arr[0] = from_i ... return temp_idx_arr[:1] # array with one signal >>> @njit ... def exit_choice_func_nb(from_i, to_i, col, temp_idx_arr): ... wait = col ... temp_idx_arr[0] = from_i + wait ... if temp_idx_arr[0] < to_i: ... return temp_idx_arr[:1] # array with one signal ... return temp_idx_arr[:0] # empty array >>> temp_idx_arr = np.empty((1,), dtype=np.int_) # reuse memory >>> en, ex = pd.DataFrame.vbt.signals.generate_both( ... (5, 3), entry_choice_func_nb, exit_choice_func_nb, ... entry_args=(temp_idx_arr,), exit_args=(temp_idx_arr,), ... index=sig.index, columns=sig.columns) >>> en a b c 2020-01-01 True True True 2020-01-02 False False False 2020-01-03 True False False 2020-01-04 False True False 2020-01-05 True False True >>> ex a b c 2020-01-01 False False False 2020-01-02 True False False 2020-01-03 False True False 2020-01-04 True False True 2020-01-05 False False False ``` """ checks.assert_numba_func(entry_choice_func_nb) checks.assert_numba_func(exit_choice_func_nb) if entry_args is None: entry_args = () if exit_args is None: exit_args = () if not isinstance(shape, tuple): shape = (shape, 1) elif isinstance(shape, tuple) and len(shape) == 1: shape = (shape[0], 1) result1, result2 = nb.generate_enex_nb( shape, entry_wait, exit_wait, entry_choice_func_nb, entry_args, exit_choice_func_nb, exit_args ) if cls.is_series(): if shape[1] > 1: raise ValueError("Use DataFrame accessor") return pd.Series(result1[:, 0], **kwargs), pd.Series(result2[:, 0], **kwargs) return pd.DataFrame(result1, **kwargs), pd.DataFrame(result2, **kwargs)