Source code for pandas_ta.trend.xsignals

# -*- coding: utf-8 -*-
from numpy import nan as npNaN
from pandas import DataFrame
from .tsignals import tsignals
from pandas_ta.utils._signals import cross_value
from pandas_ta.utils import get_offset, verify_series


[docs]def xsignals(signal, xa, xb, above:bool=True, long:bool=True, asbool:bool=None, trend_reset:int=0, trade_offset:int=None, offset:int=None, **kwargs): """Indicator: Cross Signals""" # Validate Arguments signal = verify_series(signal) offset = get_offset(offset) # Calculate Result if above: entries = cross_value(signal, xa) exits = -cross_value(signal, xb, above=False) else: entries = cross_value(signal, xa, above=False) exits = -cross_value(signal, xb) trades = entries + exits # Modify trades to fill gaps for trends trades.replace({0: npNaN}, inplace=True) trades.interpolate(method="pad", inplace=True) trades.fillna(0, inplace=True) trends = (trades > 0).astype(int) if not long: trends = 1 - trends tskwargs = { "asbool":asbool, "trade_offset":trade_offset, "trend_reset":trend_reset, "offset":offset } df = tsignals(trends, **tskwargs) # Offset handled by tsignals DataFrame({ f"XS_LONG": df.TS_Trends, f"XS_SHORT": 1 - df.TS_Trends }) # Handle fills if "fillna" in kwargs: df.fillna(kwargs["fillna"], inplace=True) if "fill_method" in kwargs: df.fillna(method=kwargs["fill_method"], inplace=True) # Name & Category df.name = f"XS" df.category = "trend" return df
xsignals.__doc__ = \ """Cross Signals (XSIGNALS) Cross Signals returns Trend Signal (TSIGNALS) results for Signal Crossings. This is useful for indicators like RSI, ZSCORE, et al where one wants trade Entries and Exits (and Trends). Cross Signals has two kinds of modes: above and long. The first mode 'above', default True, xsignals determines if the signal first crosses above 'xa' and then below 'xb'. If 'above' is False, xsignals determines if the signal first crosses below 'xa' and then above 'xb'. The second mode 'long', default True, passes the long trend result into tsignals so it can determine the appropriate Entries and Exits. When 'long' is False, it does the same but for the short side. Example: # These are two different outcomes and depends on the indicator and it's # characteristics. Please check BOTH outcomes BEFORE making an Issue. rsi = df.ta.rsi() # Returns tsignal DataFrame when RSI crosses above 20 and then below 80 ta.xsignals(rsi, 20, 80, above=True) # Returns tsignal DataFrame when RSI crosses below 20 and then above 80 ta.xsignals(rsi, 20, 80, above=False) Source: Kevin Johnson Calculation: Default Inputs: asbool=False, trend_reset=0, trade_offset=0, drift=1 trades = trends.diff().shift(trade_offset).fillna(0).astype(int) entries = (trades > 0).astype(int) exits = (trades < 0).abs().astype(int) Args: above (bool): When the signal crosses above 'xa' first and then 'xb'. When False, then when the signal crosses below 'xa' first and then 'xb'. Default: True long (bool): Passes the long trend into tsignals' trend argument. When False, it passes the short trend into tsignals trend argument. Default: True drift (int): The difference period. Default: 1 offset (int): How many periods to offset the result. Default: 0 # TSIGNAL Passthrough arguments asbool (bool): If True, it converts the Trends, Entries and Exits columns to booleans. When boolean, it is also useful for backtesting with vectorbt's Portfolio.from_signal(close, entries, exits) Default: False trend_reset (value): Value used to identify if a trend has ended. Default: 0 trade_offset (value): Value used shift the trade entries/exits Use 1 for backtesting and 0 for live. Default: 0 Kwargs: fillna (value, optional): pd.DataFrame.fillna(value) fill_method (value, optional): Type of fill method Returns: pd.DataFrame with columns: Trends (trend: 1, no trend: 0), Trades (Enter: 1, Exit: -1, Otherwise: 0), Entries (entry: 1, nothing: 0), Exits (exit: 1, nothing: 0) """