Skip to content
New: Star-import, signal unraveling, Python 3.12 support, and more

#
factory module

Factory for building signal generators.

The signal factory class SignalFactory extends IndicatorFactory to offer a convenient way to create signal generators of any complexity. By providing it with information such as entry and exit functions and the names of inputs, parameters, and outputs, it will create a stand-alone class capable of generating signals for an arbitrary combination of inputs and parameters.

## SignalFactory class

    SignalFactory(
        *args,
        mode=2,
        input_names=None,
        attr_settings=None,
        **kwargs
    )

A factory for building signal generators.

Extends IndicatorFactory with place functions.

Generates a fixed number of outputs (depending upon `mode`). If you need to generate other outputs, use in-place outputs (via `in_output_names`).

See FactoryMode for supported generation modes.

Other arguments are passed to IndicatorFactory.

A factory for creating new indicators.

Initialize `IndicatorFactory` to create a skeleton and then use a class method such as `IndicatorFactory.with_custom_func` to bind a calculation function to the skeleton.

Args

`class_name` :`str`
  Name for the created indicator class.
`class_docstring` :`str`
  Docstring for the created indicator class.
`module_name` :`str`
  Name of the module the class originates from.
`short_name` :`str`

  Short name of the indicator.

  Defaults to lower-case `class_name`.

`prepend_name` :`bool`
  Whether to prepend `short_name` to each parameter level.
`input_names` :`list` of `str`
  List with input names.
`param_names` :`list` of `str`
  List with parameter names.
`in_output_names` :`list` of `str`

  List with in-output names.

  An in-place output is an output that is not returned but modified in-place. Some advantages of such outputs include:

  1) they don't need to be returned, 2) they can be passed between functions as easily as inputs, 3) they can be provided with already allocated data to safe memory, 4) if data or default value are not provided, they are created empty to not occupy memory.

`output_names` :`list` of `str`
  List with output names.
`output_flags` :`dict`
  Dictionary of in-place and regular output flags.
`lazy_outputs` :`dict`
  Dictionary with user-defined functions that will be bound to the indicator class and wrapped with `property` if not already wrapped.
`attr_settings` :`dict`

  Dictionary with attribute settings.

  Attributes can be `input_names`, `in_output_names`, `output_names`, and `lazy_outputs`.

  Following keys are accepted:

  - `dtype`: Data type used to determine which methods to generate around this attribute. Set to None to disable. Default is `np.float_`. Can be set to instance of `collections.namedtuple` acting as enumerated type, or any other mapping; It will then create a property with suffix `readable` that contains data in a string format.
  - `enum_unkval`: Value to be considered as unknown. Applies to enumerated data types only.
  - `make_cacheable`: Whether to make the property cacheable. Applies to inputs only.
`metrics` :`dict`

  Metrics supported by StatsBuilderMixin.stats().

  If dict, will be converted to Config.

`stats_defaults` :`callable` or `dict`

  Defaults for StatsBuilderMixin.stats().

  If dict, will be converted into a property.

`subplots` :`dict`

  Subplots supported by PlotsBuilderMixin.plots().

  If dict, will be converted to Config.

`plots_defaults` :`callable` or `dict`

  Defaults for PlotsBuilderMixin.plots().

  If dict, will be converted into a property.

`**kwargs`
  Custom keyword arguments passed to the config.

Note

The `__init__` method is not used for running the indicator, for this use `run`. The reason for this is indexing, which requires a clean `__init__` method for creating a new indicator object with newly indexed attributes.

Superclasses

- Cacheable
- Chainable
- Comparable
- Configured
- HasSettings
- IndicatorFactory
- Pickleable
- Prettified

Inherited members

- Cacheable.get_ca_setup()
- Chainable.pipe()
- Configured.copy()
- Configured.equals()
- Configured.get_writeable_attrs()
- Configured.prettify()
- Configured.replace()
- Configured.resolve_merge_kwargs()
- Configured.update_config()
- HasSettings.get_path_setting()
- HasSettings.get_path_settings()
- HasSettings.get_setting()
- HasSettings.get_settings()
- HasSettings.has_path_setting()
- HasSettings.has_path_settings()
- HasSettings.has_setting()
- HasSettings.has_settings()
- HasSettings.reset_settings()
- HasSettings.resolve_setting()
- HasSettings.resolve_settings_paths()
- HasSettings.set_settings()
- IndicatorFactory.Indicator
- IndicatorFactory.attr_settings
- IndicatorFactory.class_docstring
- IndicatorFactory.class_name
- IndicatorFactory.config
- IndicatorFactory.deregister_custom_indicator()
- IndicatorFactory.find_ta_indicator()
- IndicatorFactory.find_technical_indicator()
- IndicatorFactory.from_custom_techcon()
- IndicatorFactory.from_expr()
- IndicatorFactory.from_pandas_ta()
- IndicatorFactory.from_ta()
- IndicatorFactory.from_talib()
- IndicatorFactory.from_techcon()
- IndicatorFactory.from_technical()
- IndicatorFactory.from_wqa101()
- IndicatorFactory.get_custom_indicator()
- IndicatorFactory.get_indicator()
- IndicatorFactory.in_output_names
- IndicatorFactory.input_names
- IndicatorFactory.lazy_outputs
- IndicatorFactory.list_builtin_locations()
- IndicatorFactory.list_custom_indicators()
- IndicatorFactory.list_custom_locations()
- IndicatorFactory.list_indicators()
- IndicatorFactory.list_locations()
- IndicatorFactory.list_pandas_ta_indicators()
- IndicatorFactory.list_ta_indicators()
- IndicatorFactory.list_talib_indicators()
- IndicatorFactory.list_techcon_indicators()
- IndicatorFactory.list_technical_indicators()
- IndicatorFactory.list_vbt_indicators()
- IndicatorFactory.list_wqa101_indicators()
- IndicatorFactory.match_location()
- IndicatorFactory.metrics
- IndicatorFactory.module_name
- IndicatorFactory.output_flags
- IndicatorFactory.output_names
- IndicatorFactory.param_names
- IndicatorFactory.parse_pandas_ta_config()
- IndicatorFactory.parse_ta_config()
- IndicatorFactory.parse_technical_config()
- IndicatorFactory.plots_defaults
- IndicatorFactory.prepend_name
- IndicatorFactory.rec_state
- IndicatorFactory.register_custom_indicator()
- IndicatorFactory.short_name
- IndicatorFactory.split_indicator_name()
- IndicatorFactory.stats_defaults
- IndicatorFactory.subplots
- IndicatorFactory.with_apply_func()
- IndicatorFactory.with_custom_func()
- Pickleable.decode_config()
- Pickleable.decode_config_node()
- Pickleable.dumps()
- Pickleable.encode_config()
- Pickleable.encode_config_node()
- Pickleable.file_exists()
- Pickleable.getsize()
- Pickleable.load()
- Pickleable.loads()
- Pickleable.modify_state()
- Pickleable.resolve_file_path()
- Pickleable.save()

### mode property

Factory mode.

### with_place_func method

    SignalFactory.with_place_func(
        entry_place_func_nb=None,
        exit_place_func_nb=None,
        generate_func_nb=generate_nb,
        generate_ex_func_nb=generate_ex_nb,
        generate_enex_func_nb=generate_enex_nb,
        cache_func=None,
        entry_settings=None,
        exit_settings=None,
        cache_settings=None,
        jit_kwargs=None,
        **kwargs
    )

Build signal generator class around entry and exit placement functions.

A placement function is simply a function that places signals. There are two types of it: entry placement function and exit placement function. Each placement function takes broadcast time series, broadcast in-place output time series, broadcast parameter arrays, and other arguments, and returns an array of indices corresponding to chosen signals. See generate_nb().

Args

`entry_place_func_nb` :`callable`

  `place_func_nb` that returns indices of entries.

  Defaults to first_place_nb() for `FactoryMode.Chain`.

`exit_place_func_nb` :`callable`
  `place_func_nb` that returns indices of exits.
`generate_func_nb` :`callable`

  Entry generation function.

  Defaults to generate_nb().

`generate_ex_func_nb` :`callable`

  Exit generation function.

  Defaults to generate_ex_nb().

`generate_enex_func_nb` :`callable`

  Entry and exit generation function.

  Defaults to generate_enex_nb().

`cache_func` :`callable`

  A caching function to preprocess data beforehand.

  All returned objects will be passed as last arguments to placement functions.

`entry_settings` :`dict`
  Settings dict for `entry_place_func_nb`.
`exit_settings` :`dict`
  Settings dict for `exit_place_func_nb`.
`cache_settings` :`dict`
  Settings dict for `cache_func`.
`jit_kwargs` :`dict`

  Keyword arguments passed to `@njit` decorator of the parameter selection function.

  By default, has `nogil` set to True.

`**kwargs`
  Keyword arguments passed to `IndicatorFactory.with_custom_func`.

Note

Choice functions must be Numba-compiled.

Which inputs, parameters and arguments to pass to each function must be explicitly indicated in the function's settings dict. By default, nothing is passed.

Passing keyword arguments directly to the placement functions is not supported. Use `pass_kwargs` in a settings dict to pass keyword arguments as positional.

Settings dict of each function can have the following keys:

Attributes

`pass_inputs` :`list` of `str`

  Input names to pass to the placement function.

  Defaults to []. Order matters. Each name must be in `input_names`.

`pass_in_outputs` :`list` of `str`

  In-place output names to pass to the placement function.

  Defaults to []. Order matters. Each name must be in `in_output_names`.

`pass_params` :`list` of `str`

  Parameter names to pass to the placement function.

  Defaults to []. Order matters. Each name must be in `param_names`.

`pass_kwargs` :`dict`, `list` of `str` or `list` of `tuple`

  Keyword arguments from `kwargs` dict to pass as positional arguments to the placement function.

  Defaults to []. Order matters.

  If any element is a tuple, must contain the name and the default value. If any element is a string, the default value is None.

  Built-in keys include:

  - `input_shape`: Input shape if no input time series passed. Default is provided by the pipeline if `pass_input_shape` is True.
  - `wait`: Number of ticks to wait before placing signals. Default is 1.
  - `until_next`: Whether to place signals up to the next entry signal. Default is True. Applied in `generate_ex_func_nb` only.
  - `skip_until_exit`: Whether to skip processing entry signals until the next exit. Default is False. Applied in `generate_ex_func_nb` only.
  - `pick_first`: Whether to stop as soon as the first exit signal is found. Default is False with `FactoryMode.Entries`, otherwise is True.
  - `temp_idx_arr`: Empty integer array used to temporarily store indices. Default is an automatically generated array of shape `input_shape[0]`. You can also pass `temp_idx_arr1`, `temp_idx_arr2`, etc. to generate multiple.
`pass_cache` :`bool`

  Whether to pass cache from `cache_func` to the placement function.

  Defaults to False. Cache is passed unpacked.

The following arguments can be passed to `run` and `run_combs` methods:

Args

`*args`
  Can be used instead of `place_args`.
`place_args` :`tuple`
  Arguments passed to any placement function (depending on the mode).
`entry_place_args` :`tuple`
  Arguments passed to the entry placement function.
`exit_place_args` :`tuple`
  Arguments passed to the exit placement function.
`entry_args` :`tuple`
  Alias for `entry_place_args`.
`exit_args` :`tuple`
  Alias for `exit_place_args`.
`cache_args` :`tuple`
  Arguments passed to the cache function.
`entry_kwargs` :`tuple`
  Settings for the entry placement function. Also contains arguments passed as positional if in `pass_kwargs`.
`exit_kwargs` :`tuple`
  Settings for the exit placement function. Also contains arguments passed as positional if in `pass_kwargs`.
`cache_kwargs` :`tuple`
  Settings for the cache function. Also contains arguments passed as positional if in `pass_kwargs`.
`return_cache` :`bool`
  Whether to return only cache.
`use_cache` :`any`
  Cache to use.
`**kwargs`
  Default keyword arguments (depending on the mode).

For more arguments, see IndicatorBase.run_pipeline().

Usage

- The simplest signal indicator that places True at the very first index:

    >>> from vectorbtpro import *

    >>> @njit
    ... def entry_place_func_nb(c):
    ...     c.out[0] = True
    ...     return 0

    >>> @njit
    ... def exit_place_func_nb(c):
    ...     c.out[0] = True
    ...     return 0

    >>> MySignals = vbt.SignalFactory().with_place_func(
    ...     entry_place_func_nb=entry_place_func_nb,
    ...     exit_place_func_nb=exit_place_func_nb,
    ...     entry_kwargs=dict(wait=1),
    ...     exit_kwargs=dict(wait=1)
    ... )

    >>> my_sig = MySignals.run(input_shape=(3, 3))
    >>> my_sig.entries
           0      1      2
    0   True   True   True
    1  False  False  False
    2   True   True   True
    >>> my_sig.exits
           0      1      2
    0  False  False  False
    1   True   True   True
    2  False  False  False

- Take the first entry and place an exit after waiting `n` ticks. Find the next entry and repeat. Test three different `n` values.

    >>> from vectorbtpro.signals.factory import SignalFactory

    >>> @njit
    ... def wait_place_nb(c, n):
    ...     if n < len(c.out):
    ...         c.out[n] = True
    ...         return n
    ...     return -1

    >>> # Build signal generator
    >>> MySignals = SignalFactory(
    ...     mode='chain',
    ...     param_names=['n']
    ... ).with_place_func(
    ...     exit_place_func_nb=wait_place_nb,
    ...     exit_settings=dict(
    ...         pass_params=['n']
    ...     )
    ... )

    >>> # Run signal generator
    >>> entries = [True, True, True, True, True]
    >>> my_sig = MySignals.run(entries, [0, 1, 2])

    >>> my_sig.entries  # input entries
    custom_n     0     1     2
    0         True  True  True
    1         True  True  True
    2         True  True  True
    3         True  True  True
    4         True  True  True

    >>> my_sig.new_entries  # output entries
    custom_n      0      1      2
    0          True   True   True
    1         False  False  False
    2          True  False  False
    3         False   True  False
    4          True  False   True

    >>> my_sig.exits  # output exits
    custom_n      0      1      2
    0         False  False  False
    1          True  False  False
    2         False   True  False
    3          True  False   True
    4         False  False  False

- To combine multiple iterative signals, you would need to create a custom placement function. Here is an example of combining two random generators using "OR" rule (the first signal wins):

    >>> from vectorbtpro.indicators.configs import flex_elem_param_config
    >>> from vectorbtpro.signals.factory import SignalFactory
    >>> from vectorbtpro.signals.nb import rand_by_prob_place_nb

    >>> # Enum to distinguish random generators
    >>> RandType = namedtuple('RandType', ['R1', 'R2'])(0, 1)

    >>> # Define exit placement function
    >>> @njit
    ... def rand_exit_place_nb(c, rand_type, prob1, prob2):
    ...     for out_i in range(len(c.out)):
    ...         if np.random.uniform(0, 1) < prob1:
    ...             c.out[out_i] = True
    ...             rand_type[c.from_i + out_i] = RandType.R1
    ...             return out_i
    ...         if np.random.uniform(0, 1) < prob2:
    ...             c.out[out_i] = True
    ...             rand_type[c.from_i + out_i] = RandType.R2
    ...             return out_i
    ...     return -1

    >>> # Build signal generator
    >>> MySignals = SignalFactory(
    ...     mode='chain',
    ...     in_output_names=['rand_type'],
    ...     param_names=['prob1', 'prob2'],
    ...     attr_settings=dict(
    ...         rand_type=dict(dtype=RandType)  # creates rand_type_readable
    ...     )
    ... ).with_place_func(
    ...     exit_place_func_nb=rand_exit_place_nb,
    ...     exit_settings=dict(
    ...         pass_in_outputs=['rand_type'],
    ...         pass_params=['prob1', 'prob2']
    ...     ),
    ...     param_settings=dict(
    ...         prob1=flex_elem_param_config,  # param per frame/row/col/element
    ...         prob2=flex_elem_param_config
    ...     ),
    ...     rand_type=-1  # fill with this value
    ... )

    >>> # Run signal generator
    >>> entries = [True, True, True, True, True]
    >>> my_sig = MySignals.run(entries, [0., 1.], [0., 1.], param_product=True)

    >>> my_sig.new_entries
    custom_prob1           0.0           1.0
    custom_prob2    0.0    1.0    0.0    1.0
    0              True   True   True   True
    1             False  False  False  False
    2             False   True   True   True
    3             False  False  False  False
    4             False   True   True   True

    >>> my_sig.exits
    custom_prob1           0.0           1.0
    custom_prob2    0.0    1.0    0.0    1.0
    0             False  False  False  False
    1             False   True   True   True
    2             False  False  False  False
    3             False   True   True   True
    4             False  False  False  False

    >>> my_sig.rand_type_readable
    custom_prob1     0.0     1.0
    custom_prob2 0.0 1.0 0.0 1.0
    0
    1                 R2  R1  R1
    2
    3                 R2  R1  R1
    4

#### Cookie consent

We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.

- Google Analytics
- GitHub

Manage settings