investfly.models.indicator

Indicator models

class ParamType(builtins.str, enum.Enum):

Indicator Param Type

INTEGER = INTEGER
FLOAT = FLOAT
BOOLEAN = BOOLEAN
STRING = STRING
BARINTERVAL = BARINTERVAL
class IndicatorValueType(builtins.str, enum.Enum):

Indicator ValueType can possibly used by Investfly to validate expression and optimize experience for users For e.g, all Indicators of same valueType can be plotted in the same y-axis

PRICE = PRICE
PERCENT = PERCENT
RATIO = RATIO
BOOLEAN = BOOLEAN
NUMBER = NUMBER
class IndicatorId(builtins.str, enum.Enum):

Technical indicators supported by Investfly.

This enum lists all standard technical indicators that can be used in trading strategies for technical analysis. The enum values are string identifiers that must be used when calling computeIndicatorSeries() in DataService.

Note: The enum values are strings (not the enum names) to support both standard and custom indicators. When using standard indicators, use the .value property or the string directly (e.g., "SMA" or StandardIndicatorId.SMA.value).

AVGVOL = AVGVOLUME
HIGH_52_WEEK = HIGH52WEEK
LOW_52_WEEK = LOW52WEEK
LASTBAR = LASTBAR
DRAWDOWN = DRAWDOWN
PERCENTCHANGE = PRICECHANGEPCT
SMA = SMA
EMA = EMA
TEMA = TEMA
DEMA = DEMA
KAMA = KAMA
MAMA = MAMA
FAMA = FAMA
MACD = MACD
MACDS = MACDS
ADX = ADX
ADXR = ADXR
PLUS_DI = PLUS_DI
MINUS_DI = MINUS_DI
DX = DX
PSAR = PSAR
TRIX = TRIX
ICHIMOKU = ICHIMOKU
KELTNER = KELTNER
RSI = RSI
ROC = ROC
CCI = CCI
CMO = CMO
CMO_SMOOTHED = CMO_SMOOTHED
PPO = PPO
APO = APO
ULTIMATE_OSC = ULTIMATE_OSC
BOP = BOP
WILLIAM_R = WILLIAM_R
STOCHASTICS = STOCHASTICS
FAST_STOCHASTIC_OSC = FAST_STOCHASTIC_OSC
SLOW_STOCHASTIC_OSC = SLOW_STOCHASTIC_OSC
STOCH = STOCH
STOCHF = STOCHF
STOCHRSI = STOCHRSI
AROONOSC = AROONOSC
AROON = AROON
AROONDOWN = AROONDOWN
MFI = MFI
ATR = ATR
STD_DEV = STD_DEV
BBAND = BBAND
UPPER_BBAND = UPPER_BBAND
LOWER_BBAND = LOWER_BBAND
UPPERBBAND = UPPERBBAND
LOWERBBAND = LOWERBBAND
OBV = OBV
CMF = CMF
VWAP = VWAP
RVOL = RVOL
AVGPRICE = AVGPRICE
MEDIAN_PRICE = MEDIAN_PRICE
MEDPRICE = MEDPRICE
TYPICAL_PRICE = TYPICAL_PRICE
TYPPRICE = TYPPRICE
WCLPRICE = WCLPRICE
BARPRICE = BARPRICE
MAX = MAX
MIN = MIN
DOJI = DOJI
CDLDOJI = CDLDOJI
HAMMER = HAMMER
CDLHAMMER = CDLHAMMER
INVERTED_HAMMER = INVERTED_HAMMER
DRAGONFLY_DOJI = DRAGONFLY_DOJI
GRAVESTONE_DOJI = GRAVESTONE_DOJI
HANGING_MAN = HANGING_MAN
CDLENGULFING = CDLENGULFING
CDLMORNINGSTAR = CDLMORNINGSTAR
CDLEVENINGSTAR = CDLEVENINGSTAR
CDLHARAMI = CDLHARAMI
CDLSHOOTINGSTAR = CDLSHOOTINGSTAR
CDL3BLACKCROWS = CDL3BLACKCROWS
CDL3WHITESOLDIERS = CDL3WHITESOLDIERS
CDLMARUBOZU = CDLMARUBOZU
BULLISH = BULLISH
BEARISH = BEARISH
SUPPORT = SUPPORT
RESISTANCE = RESISTANCE
class IndicatorParam:
class IndicatorParam.SMA:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.EMA:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.TEMA:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.DEMA:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.KAMA:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.MAMA:
FAST_LIMIT = 'fast_limit'
SLOW_LIMIT = 'slow_limit'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fast_limit', 'slow_limit', 'barinterval']
class IndicatorParam.FAMA:
FAST_LIMIT = 'fast_limit'
SLOW_LIMIT = 'slow_limit'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fast_limit', 'slow_limit', 'barinterval']
class IndicatorParam.UPPERBBAND:
PERIOD = 'period'
STDDEV = 'std_dev'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'std_dev', 'barinterval']
class IndicatorParam.LOWERBBAND:
PERIOD = 'period'
STDDEV = 'std_dev'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'std_dev', 'barinterval']
class IndicatorParam.ICHIMOKU:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.KELTNER:
PERIOD = 'period'
MULTIPLIER = 'multiplier'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'multiplier', 'barinterval']
class IndicatorParam.MACD:
FAST_PERIOD = 'fast_period'
SLOW_PERIOD = 'slow_period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fast_period', 'slow_period', 'barinterval']
class IndicatorParam.MACDS:
FAST_PERIOD = 'fast_period'
SLOW_PERIOD = 'slow_period'
SIGNAL_PERIOD = 'signal_period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fast_period', 'slow_period', 'signal_period', 'barinterval']
class IndicatorParam.RSI:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.ROC:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.CCI:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.ADX:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.ADXR:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.AROONOSC:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.AROON:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.AROONDOWN:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.MFI:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.CMO:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.STOCH:
FASTK_PERIOD = 'fastk_period'
SLOWK_PERIOD = 'slowk_period'
SLOWD_PERIOD = 'slowd_period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fastk_period', 'slowk_period', 'slowd_period', 'barinterval']
class IndicatorParam.STOCHF:
FASTK_PERIOD = 'fastk_period'
FASTD_PERIOD = 'fastd_period'
FASTD_MATYPE = 'fastd_matype'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fastk_period', 'fastd_period', 'fastd_matype', 'barinterval']
class IndicatorParam.STOCHRSI:
TIMEPERIOD = 'timeperiod'
FASTK_PERIOD = 'fastk_period'
FASTD_PERIOD = 'fastd_period'
FASTD_MATYPE = 'fastd_matype'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['timeperiod', 'fastk_period', 'fastd_period', 'fastd_matype', 'barinterval']
class IndicatorParam.APO:
FAST_PERIOD = 'fast_period'
SLOW_PERIOD = 'slow_period'
MATYPE = 'matype'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fast_period', 'slow_period', 'matype', 'barinterval']
class IndicatorParam.PPO:
FAST_PERIOD = 'fast_period'
SLOW_PERIOD = 'slow_period'
MATYPE = 'matype'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['fast_period', 'slow_period', 'matype', 'barinterval']
class IndicatorParam.MINUS_DI:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.PLUS_DI:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.DX:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.TRIX:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.CMF:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.AVGVOL:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.VWAP:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.RVOL:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.ATR:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.MAX:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.MIN:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class IndicatorParam.LASTBAR:
FIELD = 'field'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['field', 'barinterval']
class IndicatorParam.CDLMORNINGSTAR:
PENETRATION = 'penetration'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['penetration', 'barinterval']
class IndicatorParam.CDLEVENINGSTAR:
PENETRATION = 'penetration'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['penetration', 'barinterval']
class IndicatorParam.PSAR:
ACCELERATION = 'acceleration'
MAXIMUM = 'maximum'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['acceleration', 'maximum', 'barinterval']
class IndicatorParam.WILLIAMR:
PERIOD = 'period'
BARINTERVAL = 'barinterval'
ALL_PARAMS = ['period', 'barinterval']
class StandardParams(builtins.str, enum.Enum):

Standard/common parameters used across multiple indicators.

These parameters are common to many indicators and can be referenced using StandardParams instead of indicator-specific parameter enums.

COUNT = count
LOOKBACK = lookback
SECURITY = security
BARINTERVAL = barinterval
FIELD = field
@dataclass
class IndicatorParamSpec:

Class that represents Indicator Parameter Specification

IndicatorParamSpec( paramType: ParamType, required: bool = True, defaultValue: typing.Any | None = None, options: Optional[List[Any]] = None)
paramType: ParamType

Parameter Type (INTEGER, FLOAT, BOOLEAN, STRING, BARINTERVAL)

required: bool = True

Whether this parameter is required or optional

defaultValue: typing.Any | None = None

The default value for the parameter to auto-populate mainly in UI

options: Optional[List[Any]] = None

Valid value options (if any). If specified, then in the UI, this parameter renders as a dropdown select list. If left as None, parameter renders and freeform input text field.

PERIOD_VALUES: ClassVar[List[int]] = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 20, 24, 26, 30, 40, 50, 60, 70, 80, 90, 100, 120, 130, 140, 150, 180, 200, 250, 300]
def toDict(self) -> Dict[str, Any]:
@staticmethod
def fromDict( json_dict: Dict[str, Any]) -> IndicatorParamSpec:
class IndicatorSpec:
IndicatorSpec(name: str)
indicatorId: str
name: str
description: str
valueType: IndicatorValueType
params: Dict[str, IndicatorParamSpec]
def addParam( self, paramName: str, paramSpec: IndicatorParamSpec) -> None:
def toJsonDict(self) -> Dict[str, Any]:
@staticmethod
def fromDict( json_dict: Dict[str, Any]) -> IndicatorSpec:
def validate(self) -> None:

Validate that required fields are provided and have correct types

class Indicator(abc.ABC):

The primary class to implement a custom Indicator. A Custom Indicator is like standard indicator (e.g SMA, RSI) and can be used in any place that standard indicator can be used (e.g screener, charts, strategy etc) Investfly comes with a set of standard indicators. If you find that the indicator you want is not supported or you can a small variation (e.g SMA but with using Heikin Ashi Candles), then you can use this function

Indicators receive market data through an IndicatorDataService injected via setDataService(). This service abstracts away the security context, allowing indicators to be pure mathematical functions.

Indicator()

Initialize the indicator.

The data service will be set via setDataService() after instantiation.

dataService: IndicatorDataService
def setDataService( self, dataService: IndicatorDataService) -> None:

Set the data service for this indicator.

This method is called by IndicatorService after instantiating the indicator.

Args: dataService: The data service for accessing bars, quotes, financials, and news for a specific security.

@abstractmethod
def getIndicatorSpec(self) -> IndicatorSpec:

Return IndicatorSpec with name, description, required params, and valuetype.

See IndicatorSpec abstract class for more details.

Returns: IndicatorSpec: The indicator specification object.

@abstractmethod
def computeSeries( self, params: Dict[str, Any]) -> List[investfly.models.common.DatedValue]:

Compute indicator series based on provided parameters.

This function must return List of indicator values instead of only the most recent single value because indicator series is required to plot in the price chart and also to use in backtest.

The indicator should use self.dataService to retrieve the data it needs (bars, quotes, financials, news). The timestamps in the DatedValue must correspond to timestamps in the retrieved data.

Args: params: User supplied indicator parameter values. The keys match the keys from IndicatorSpec.params.

Note: The params[StandardParams.COUNT] parameter specifies how many indicator values the function should return in the list. - If COUNT is NOT specified: Compute and return the FULL series based on all available data. - If COUNT is specified: Return only the last COUNT values.

For optimal performance, use COUNT to only request the minimum necessary amount of historical data.
For example: to compute a 20-period SMA and return a single most recent value (`count=1`), you should request 20 bars. 
If `count=2`, you should request 21 bars; in general, for SMA, the number of bars needed is `period + count - 1`.
If COUNT is not specified, request ALL_BARS to compute the full series.

Returns: List of DatedValue representing indicator values for each time unit.

def computeCurrent( self, params: Dict[str, Any]) -> investfly.models.common.DatedValue:

Compute the current (most recent) indicator value.

This default implementation calls computeSeries() and returns the last value. If computing just the current value is more performant than computing the full series, Indicator implementations should override this method.

Args: params: User supplied indicator parameter values. Same as computeSeries().

Returns: The most recent DatedValue from the indicator series.

Raises: IndexError: If the indicator series is empty.

def validateParams(self, paramVals: Dict[str, Any]):
def addStandardParamsToDef( self, indicatorDef: IndicatorSpec):
class IndicatorDataService(abc.ABC):

Interface for accessing market data in indicators.

This interface provides market data access methods without requiring a security parameter. The security context is captured when the service is instantiated, allowing indicators to remain pure mathematical functions.

Attributes: ALL_BARS: Constant value (-1) used to retrieve all available historical bars.

ALL_BARS: int = -1

Constant for retrieving all available bars.

@abstractmethod
def getBars(self, numBars: int = -1) -> List[investfly.models.marketdata.Bar]:

Retrieve historical bars for the configured security.

The bar interval and lookback are captured when the service is instantiated. If lookback > 0, the most recent 'lookback' bars are automatically excluded from the result, effectively shifting the time window backwards.

Args: numBars: Number of bars to return. Use IndicatorDataService.ALL_BARS to retrieve all available bars.

Returns: List of Bar objects containing OHLC data in chronological order (oldest first). If lookback > 0, the result excludes the most recent 'lookback' bars.

Raises: NoDataException: If the requested data is not available.

@abstractmethod
def getNews(self) -> List[investfly.models.marketdata.StockNews]:

Retrieve latest news articles for the configured security.

This method returns recent news articles related to the configured security. News data can be used for sentiment analysis or event-driven trading strategies.

Returns: List of StockNews objects containing news articles. Returns an empty list if no news is available.

class IndicatorSeries:

Represents a series of indicator values over time. Provides methods to access the latest value and detect crossovers.

Get the most recent indicator value.

Returns: DatedValue: The latest indicator value with its timestamp

def cross_over( self, other: IndicatorSeries) -> bool:

Check if this indicator series crosses above another indicator series.

Returns True only on the bar/tick where self crosses above other. This means:

  • Previous bar: self < other
  • Current bar: self > other

Args: other: Another IndicatorSeries to compare against

Returns: bool: True if crossover occurred on the current bar/tick, False otherwise

def cross_under( self, other: IndicatorSeries) -> bool:

Check if this indicator series crosses below another indicator series.

Returns True only on the bar/tick where self crosses below other. This means:

  • Previous bar: self > other
  • Current bar: self < other

Args: other: Another IndicatorSeries to compare against

Returns: bool: True if crossunder occurred on the current bar/tick, False otherwise

def toList(self) -> List[investfly.models.common.DatedValue]:

Get all indicator values as a list.

Returns: List[DatedValue]: List of all indicator values, ordered from oldest to newest