Skip to content

hexital

hexital

Classes:

Name Description
Hexital

Hexital

Hexital(
    name: str,
    candles: Sequence[Candle],
    indicators: (
        Sequence[dict[str, Any] | Indicator] | IndicatorCollection | None
    ) = None,
    description: str | None = None,
    timeframe: TimeFramesSource | None = None,
    timeframe_fill: bool = False,
    candle_life: timedelta | None = None,
    candlestick: CandlestickType | str | None = None,
)

Methods:

Name Description
add_indicator

Add's a new indicator to Hexital strategy.

all_series

Returns a Dictionary of all the Indicators and there results in a list format.

append

append a Candle or a chronological ordered list of Candle's to the end of the Hexital Candle's. This wil only re-sample and re-calculate the new Candles, with minor overlap.

calculate

Calculates all the missing indicator readings.

calculate_index

Calculate specific index for all or specific indicator readings.

candle_pair

Return candle streams for comparing two series on this strategy.

candles

Get a set of candles by using either a Timeframe or Indicator name

candles_for

Return the candle stream for an indicator, timeframe, or OHLCV field.

exists

Checks if the given Indicator has a valid reading in latest Candle

from_settings

Reconstruct a strategy from a settings dictionary.

has_sufficient_candles

Whether registered indicators have enough bars on their candle series.

indicator

Searches hexital's indicator's and Returns the Indicator object itself.

insert

insert a Candle or a list of Candle's to the Hexital Candles. This accepts any order or placement. This will sort, re-sample and re-calculate all Candles.

minimum_candles

Largest minimum_candles among indicators on a candle series.

minimum_candles_by_indicator

minimum_candles per registered indicator, keyed by name.

minimum_candles_by_timeframe

Largest minimum_candles per candle series, keyed by timeframe label.

prepend

Prepends a Candle or a chronological ordered list of Candle's to the front of the Hexital Candle's. This will only re-sample and re-calculate the new Candles, with minor overlap.

purge

Takes Indicator name and removes all readings for said indicator.

reading

Attempts to retrieve a reading with a given Indicator name.

recalculate

Purge's all indicator reading's and re-calculates them all,

remove_indicator

Removes an indicator from running within hexital

series

Find given indicator and returns the readings as a list

Source code in hexital/core/hexital.py
def __init__(
    self,
    name: str,
    candles: Sequence[Candle],
    indicators: Sequence[dict[str, Any] | Indicator]
    | IndicatorCollection
    | None = None,
    description: str | None = None,
    timeframe: TimeFramesSource | None = None,
    timeframe_fill: bool = False,
    candle_life: timedelta | None = None,
    candlestick: CandlestickType | str | None = None,
):
    self.name = name
    self.description = description

    self._timeframe = convert_timeframe_to_timedelta(timeframe)
    self.timeframe_fill = timeframe_fill
    self.candle_life = candle_life

    self.candlestick = (
        validate_candlesticktype(candlestick) if candlestick else None
    )

    manager = CandleManager(
        list(candles),
        candle_life=self.candle_life,
        timeframe=self._timeframe,
        timeframe_fill=self.timeframe_fill,
        candlestick=self.candlestick,
    )
    self._candle_managers = [manager]

    self._indicators = {}
    if isinstance(indicators, IndicatorCollection):
        self._validate_indicators(indicators.collection_list())
    else:
        self._validate_indicators(indicators)

add_indicator

add_indicator(
    indicator: Indicator | list[Indicator | dict[str, Any]] | dict[str, Any],
)

Add's a new indicator to Hexital strategy. This accept either Indicator datatypes or dict string versions to be packed. add_indicator(SMA(period=10)) or add_indicator({"indicator": "SMA", "period": 10}) Does not automatically calculates readings.

Source code in hexital/core/hexital.py
def add_indicator(
    self, indicator: Indicator | list[Indicator | dict[str, Any]] | dict[str, Any]
):
    """Add's a new indicator to `Hexital` strategy.
    This accept either `Indicator` datatypes or dict string versions to be packed.
    `add_indicator(SMA(period=10))` or `add_indicator({"indicator": "SMA", "period": 10})`
    Does not automatically calculates readings."""
    indicators = indicator if isinstance(indicator, list) else [indicator]

    self._validate_indicators(indicators)

all_series

all_series() -> dict[str, list[Reading]]

Returns a Dictionary of all the Indicators and there results in a list format.

Source code in hexital/core/hexital.py
def all_series(self) -> dict[str, list[Reading]]:
    """Returns a Dictionary of all the Indicators and there results in a list format."""
    return {
        name: indicator.series() for name, indicator in self._indicators.items()
    }

append

append(candles: Candles)

append a Candle or a chronological ordered list of Candle's to the end of the Hexital Candle's. This wil only re-sample and re-calculate the new Candles, with minor overlap.

Parameters:

Name Type Description Default
candles Candles

The Candle or List of Candle's to appended.

required
Source code in hexital/core/hexital.py
def append(self, candles: Candles):
    """append a Candle or a chronological ordered list of Candle's to the end of the Hexital Candle's. This wil only re-sample and re-calculate the new Candles, with minor overlap.

    Args:
        candles: The Candle or List of Candle's to appended.
    """
    candles_ = parse_candles(candles)
    admitted = set()
    for candle_manager in self._candle_managers:
        candle_manager._append_parsed(candles_, admitted=admitted)

    self.calculate()

calculate

calculate(name: str | None = None)

Calculates all the missing indicator readings.

Source code in hexital/core/hexital.py
def calculate(self, name: str | None = None):
    """Calculates all the missing indicator readings."""
    if name is not None:
        if indicator := self._indicators.get(name):
            indicator.calculate()
    else:
        for indicator in self._indicators.values():
            indicator.calculate()

calculate_index

calculate_index(
    name: str | None = None, index: int = -1, end_index: int | None = None
)

Calculate specific index for all or specific indicator readings.

Source code in hexital/core/hexital.py
def calculate_index(
    self, name: str | None = None, index: int = -1, end_index: int | None = None
):
    """Calculate specific index for all or specific indicator readings."""
    if name is not None:
        if indicator := self._indicators.get(name):
            indicator.calculate_index(index, end_index)
    else:
        for indicator in self._indicators.values():
            indicator.calculate_index(index, end_index)

candle_pair

candle_pair(
    indicator: str, indicator_cmp: str
) -> tuple[list[Candle], list[Candle]]

Return candle streams for comparing two series on this strategy.

Source code in hexital/core/hexital.py
def candle_pair(
    self, indicator: str, indicator_cmp: str
) -> tuple[list[Candle], list[Candle]]:
    """Return candle streams for comparing two series on this strategy."""
    if indicator_cmp in ({"open", "high", "low", "close", "volume"}):
        stream = self.candles_for(indicator)
        return stream, stream
    if indicator in ({"open", "high", "low", "close", "volume"}):
        stream = self.candles_for(indicator_cmp)
        return stream, stream

    return self.candles_for(indicator), self.candles_for(indicator_cmp)

candles

candles(name: TimeFramesSource | None = None) -> list[Candle]

Get a set of candles by using either a Timeframe or Indicator name

Source code in hexital/core/hexital.py
def candles(self, name: TimeFramesSource | None = None) -> list[Candle]:
    """Get a set of candles by using either a Timeframe or Indicator name"""
    name_ = name if name else self._candle_managers[0].name
    timeframe_name = convert_timeframe_to_str(name)

    name_ = timeframe_name if timeframe_name else name_

    if isinstance(name_, str):
        if manager := next(
            (m for m in self._candle_managers if m.name == name_), None
        ):
            return manager.candles
        for manager in self._candle_managers:
            if manager.find_indicator(name_):
                return manager.candles

    return []

candles_for

candles_for(name: str) -> list[Candle]

Return the candle stream for an indicator, timeframe, or OHLCV field.

Source code in hexital/core/hexital.py
def candles_for(self, name: str) -> list[Candle]:
    """Return the candle stream for an indicator, timeframe, or OHLCV field."""
    if name in ({"open", "high", "low", "close", "volume"}):
        return self._candle_managers[0].candles
    return self.candles(name)

exists

exists(name: str) -> bool

Checks if the given Indicator has a valid reading in latest Candle

Source code in hexital/core/hexital.py
def exists(self, name: str) -> bool:
    """Checks if the given Indicator has a valid reading in latest Candle"""
    value = self.reading(name)
    if isinstance(value, dict):
        return any(v is not None for v in value.values())
    return value is not None

from_settings classmethod

from_settings(
    settings: dict[str, Any], candles: Sequence[Candle] | None = None
) -> Hexital

Reconstruct a strategy from a settings dictionary.

Source code in hexital/core/hexital.py
@classmethod
def from_settings(
    cls,
    settings: dict[str, Any],
    candles: Sequence[Candle] | None = None,
) -> Hexital:
    """Reconstruct a strategy from a settings dictionary."""
    config = decode_settings(copy(settings))

    try:
        name = config.pop("name")
    except KeyError as exc:
        raise InvalidIndicator("Strategy settings missing required 'name'") from exc

    if candles is None:
        candles = config.pop("candles", [])
    else:
        config.pop("candles", None)

    indicators = config.pop("indicators", None)
    return cls(name, list(candles), indicators=indicators, **config)

has_sufficient_candles

has_sufficient_candles(timeframe: TimeFramesSource | None = None) -> bool

Whether registered indicators have enough bars on their candle series.

With no timeframe, checks every registered indicator. With a timeframe, checks only indicators on that series (e.g. "T10", "DEFAULT").

Source code in hexital/core/hexital.py
def has_sufficient_candles(
    self, timeframe: TimeFramesSource | None = None
) -> bool:
    """Whether registered indicators have enough bars on their candle series.

    With no ``timeframe``, checks every registered indicator. With a
    ``timeframe``, checks only indicators on that series (e.g. ``"T10"``,
    ``"DEFAULT"``).
    """
    if not self._indicators:
        return len(self.candles(timeframe)) > 0

    indicators = self._indicators_by_timeframe(timeframe)
    if not indicators:
        return False

    return all(indicator.is_ready for indicator in indicators)

indicator

indicator(name: str) -> Indicator | None

Searches hexital's indicator's and Returns the Indicator object itself.

Source code in hexital/core/hexital.py
def indicator(self, name: str) -> Indicator | None:
    """Searches hexital's indicator's and Returns the Indicator object itself."""
    return self._indicators.get(name)

insert

insert(candles: Candles)

insert a Candle or a list of Candle's to the Hexital Candles. This accepts any order or placement. This will sort, re-sample and re-calculate all Candles.

Parameters:

Name Type Description Default
candles Candles

The Candle or List of Candle's to inserted.

required
Source code in hexital/core/hexital.py
def insert(self, candles: Candles):
    """insert a Candle or a list of Candle's to the Hexital Candles. This accepts any order or placement. This will sort, re-sample and re-calculate all Candles.

    Args:
        candles: The Candle or List of Candle's to inserted.
    """
    candles_ = parse_candles(candles)
    admitted = set()
    for candle_manager in self._candle_managers:
        candle_manager._insert_parsed(candles_, admitted=admitted)

    self.calculate_index(index=0, end_index=-1)

minimum_candles

minimum_candles(timeframe: TimeFramesSource | None = None) -> int

Largest minimum_candles among indicators on a candle series.

With no timeframe, considers every registered indicator. With a timeframe, only indicators on that series (e.g. "T10", "DEFAULT"). Counts are in that series' bar units — pair with has_sufficient_candles(timeframe=...) to check readiness.

Source code in hexital/core/hexital.py
def minimum_candles(
    self, timeframe: TimeFramesSource | None = None
) -> int:
    """Largest ``minimum_candles`` among indicators on a candle series.

    With no ``timeframe``, considers every registered indicator. With a
    ``timeframe``, only indicators on that series (e.g. ``"T10"``,
    ``"DEFAULT"``). Counts are in that series' bar units — pair with
    ``has_sufficient_candles(timeframe=...)`` to check readiness.
    """
    indicators = self._indicators_by_timeframe(timeframe)
    if not indicators:
        return 0
    return max(indicator.minimum_candles for indicator in indicators)

minimum_candles_by_indicator

minimum_candles_by_indicator(
    indicator: Indicator | None = None,
) -> dict[str, int]

minimum_candles per registered indicator, keyed by name.

Source code in hexital/core/hexital.py
def minimum_candles_by_indicator(
    self, indicator: Indicator | None = None
) -> dict[str, int]:
    """``minimum_candles`` per registered indicator, keyed by name."""
    if indicator is None:
        return {
            ind.name: ind.minimum_candles for ind in self._indicators.values()
        }
    if indicator.name in self._indicators:
        return {indicator.name: indicator.minimum_candles}
    return {}

minimum_candles_by_timeframe

minimum_candles_by_timeframe() -> dict[str, int]

Largest minimum_candles per candle series, keyed by timeframe label.

Source code in hexital/core/hexital.py
def minimum_candles_by_timeframe(self) -> dict[str, int]:
    """Largest ``minimum_candles`` per candle series, keyed by timeframe label."""
    by_timeframe: dict[str, int] = {}
    for indicator in self._indicators.values():
        key = self._timeframe_label(indicator.candle_manager.timeframe)
        by_timeframe[key] = max(
            by_timeframe.get(key, 0), indicator.minimum_candles
        )
    return by_timeframe

prepend

prepend(candles: Candles)

Prepends a Candle or a chronological ordered list of Candle's to the front of the Hexital Candle's. This will only re-sample and re-calculate the new Candles, with minor overlap.

Parameters:

Name Type Description Default
candles Candles

The Candle or List of Candle's to prepend.

required
Source code in hexital/core/hexital.py
def prepend(self, candles: Candles):
    """Prepends a Candle or a chronological ordered list of Candle's to the front of the Hexital Candle's. This will only re-sample and re-calculate the new Candles, with minor overlap.

    Args:
        candles: The Candle or List of Candle's to prepend.
    """
    candles_ = parse_candles(candles)
    admitted = set()
    for candle_manager in self._candle_managers:
        candle_manager._prepend_parsed(candles_, admitted=admitted)
    self.calculate()

purge

purge(source: Source | None = None)

Takes Indicator name and removes all readings for said indicator. Indicator name must be exact

Source code in hexital/core/hexital.py
def purge(self, source: Source | None = None):
    """Takes Indicator name and removes all readings for said indicator.
    Indicator name must be exact"""
    if not source:
        for indicator in self._indicators.values():
            indicator.purge()
    elif indicator := self._find_indicator(source):
        indicator.purge()

reading

reading(source: Source, index: int = -1) -> Reading

Attempts to retrieve a reading with a given Indicator name. name can use ~hexital.core.constants.NESTED_DELI to find a nested reading, e.g. MACD_12_26_9:signal

Source code in hexital/core/hexital.py
def reading(self, source: Source, index: int = -1) -> Reading:
    """Attempts to retrieve a reading with a given Indicator name.
    `name` can use `~hexital.core.constants.NESTED_DELI` to find a nested
    reading, e.g. ``MACD_12_26_9:signal``
    """
    return self._find_reading(source, index)

recalculate

recalculate(source: Source | None = None)

Purge's all indicator reading's and re-calculates them all, ideal for changing an indicator parameters midway.

Source code in hexital/core/hexital.py
def recalculate(self, source: Source | None = None):
    """Purge's all indicator reading's and re-calculates them all,
    ideal for changing an indicator parameters midway."""
    if not source:
        for indicator in self._indicators.values():
            indicator.purge()
            indicator.calculate()
    elif indicator := self._find_indicator(source):
        indicator.purge()
        indicator.calculate()

remove_indicator

remove_indicator(source: Source)

Removes an indicator from running within hexital

Source code in hexital/core/hexital.py
def remove_indicator(self, source: Source):
    """Removes an indicator from running within hexital"""
    indicator = self._find_indicator(source)
    if not indicator:
        return

    indicator.purge()
    self._indicators.pop(indicator.name)

series

series(source: Source) -> list[Reading]

Find given indicator and returns the readings as a list Full Name of the indicator E.G EMA_12 OR MACD_12_26_9:signal

Source code in hexital/core/hexital.py
def series(self, source: Source) -> list[Reading]:
    """Find given indicator and returns the readings as a list
    Full Name of the indicator E.G `EMA_12` OR `MACD_12_26_9:signal`"""
    return self._find_series(source)