feat: init the repo
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
Writing a plugin
|
||||
================
|
||||
|
||||
The plugin registry lets you register custom indicator functions and call them by name
|
||||
alongside built-in indicators. This page describes the **plugin contract**, how to
|
||||
register and run plugins, and a full example.
|
||||
|
||||
Plugin contract
|
||||
---------------
|
||||
|
||||
A plugin is a **callable** (function or callable object) that satisfies:
|
||||
|
||||
1. **Signature**
|
||||
- At least one positional argument that is array-like (e.g. ``close``, ``high``, ``low``).
|
||||
- Optional ``*args`` and ``**kwargs`` for parameters (e.g. ``timeperiod=14``).
|
||||
- :func:`ferro_ta.registry.run` forwards all ``*args`` and ``**kwargs`` to the callable.
|
||||
|
||||
2. **Return type**
|
||||
- A single ``numpy.ndarray``, or
|
||||
- A tuple of ``numpy.ndarray`` (for multi-output indicators).
|
||||
- Output length should match input length (same number of bars); document any exception.
|
||||
|
||||
3. **Behaviour**
|
||||
- The callable may use ``ferro_ta`` internally (e.g. call :func:`ferro_ta.RSI` and then apply another transformation).
|
||||
- Plugins run with the caller's privileges; there is no sandboxing.
|
||||
|
||||
Validation
|
||||
----------
|
||||
|
||||
:func:`ferro_ta.registry.register` checks that the provided object is callable. If not,
|
||||
it raises ``TypeError``. No strict signature check is performed at registration time
|
||||
so that valid plugins (e.g. with default arguments) are not rejected.
|
||||
|
||||
Step-by-step
|
||||
------------
|
||||
|
||||
1. **Write a function** that accepts at least one array-like and returns one or more
|
||||
arrays of the same length as the first argument.
|
||||
|
||||
2. **Register it** with :func:`ferro_ta.registry.register`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from ferro_ta.registry import register
|
||||
register("MY_INDICATOR", my_indicator_function)
|
||||
|
||||
3. **Call it by name** with :func:`ferro_ta.registry.run`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from ferro_ta.registry import run
|
||||
result = run("MY_INDICATOR", close, timeperiod=14)
|
||||
|
||||
4. **List all indicators** (built-in and registered) with :func:`ferro_ta.registry.list_indicators`.
|
||||
|
||||
Full example
|
||||
------------
|
||||
|
||||
The following plugin computes a smoothed RSI (RSI of RSI, or "double RSI") and is
|
||||
included in the repo as ``examples/custom_indicator.py``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
"""Example plugin: smoothed RSI (RSI applied to RSI values)."""
|
||||
import numpy as np
|
||||
from ferro_ta.registry import register, run, list_indicators
|
||||
from ferro_ta import RSI, SMA
|
||||
|
||||
def SMOOTH_RSI(close, timeperiod=14, smooth=3):
|
||||
"""Smoothed RSI: RSI then SMA of the RSI series."""
|
||||
rsi = RSI(close, timeperiod=timeperiod)
|
||||
return SMA(rsi, timeperiod=smooth)
|
||||
|
||||
if __name__ == "__main__":
|
||||
register("SMOOTH_RSI", SMOOTH_RSI)
|
||||
close = np.array([44.34, 44.09, 44.15, 43.61, 44.33, 44.83, 45.10, 45.15, 44.61, 44.33])
|
||||
out = run("SMOOTH_RSI", close, timeperiod=5, smooth=2)
|
||||
print("SMOOTH_RSI:", out)
|
||||
assert "SMOOTH_RSI" in list_indicators()
|
||||
|
||||
API reference
|
||||
-------------
|
||||
|
||||
- :func:`ferro_ta.registry.register` — Register a callable under a name.
|
||||
- :func:`ferro_ta.registry.unregister` — Remove a registered indicator.
|
||||
- :func:`ferro_ta.registry.get` — Return the callable for a name.
|
||||
- :func:`ferro_ta.registry.run` — Look up by name and call with given args/kwargs.
|
||||
- :func:`ferro_ta.registry.list_indicators` — Sorted list of all registered names.
|
||||
- :exc:`ferro_ta.registry.FerroTARegistryError` — Raised when a name is not found.
|
||||
|
||||
See :mod:`ferro_ta.registry` for full docstrings.
|
||||
Reference in New Issue
Block a user